LCOV - code coverage report
Current view: top level - src/fm - cp_fm_struct.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:71c3ab0) Lines: 86.9 % 244 212
Test Date: 2026-07-25 06:35:44 Functions: 88.9 % 18 16

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief represent the structure of a full matrix
      10              : !> \par History
      11              : !>      08.2002 created [fawzi]
      12              : !> \author Fawzi Mohamed
      13              : ! **************************************************************************************************
      14              : MODULE cp_fm_struct
      15              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_release,&
      16              :                                               cp_blacs_env_type
      17              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      18              :                                               cp_logger_get_default_unit_nr,&
      19              :                                               cp_logger_type,&
      20              :                                               cp_to_string
      21              :    USE machine,                         ONLY: m_cpuid_vlen,&
      22              :                                               m_flush
      23              :    USE message_passing,                 ONLY: mp_para_env_release,&
      24              :                                               mp_para_env_type
      25              : #include "../base/base_uses.f90"
      26              : 
      27              :    IMPLICIT NONE
      28              :    PRIVATE
      29              : 
      30              :    LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .TRUE.
      31              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cp_fm_struct'
      32              : 
      33              : ! the default blacs block sizes
      34              : ! consider using #ifdefs to give them the optimal values
      35              : ! these can be changed using scf_control
      36              : ! *** these are used by default
      37              :    INTEGER, PRIVATE :: optimal_blacs_col_block_size = 64
      38              :    INTEGER, PRIVATE :: optimal_blacs_row_block_size = 64
      39              :    LOGICAL, PRIVATE :: force_block_size = .FALSE.
      40              : 
      41              :    PUBLIC :: cp_fm_struct_type, cp_fm_struct_p_type
      42              :    PUBLIC :: cp_fm_struct_create, cp_fm_struct_retain, cp_fm_struct_release, &
      43              :              cp_fm_struct_equivalent, &
      44              :              cp_fm_struct_get, cp_fm_struct_double, cp_fm_struct_config, &
      45              :              cp_fm_struct_get_nrow_block, cp_fm_struct_get_ncol_block, &
      46              :              cp_fm_struct_write_info
      47              : 
      48              : ! **************************************************************************************************
      49              : !> \brief keeps the information about the structure of a full matrix
      50              : !> \param para_env the parallel environment of the matrices with this structure
      51              : !> \param context the blacs context (parallel environment for scalapack),
      52              : !>        should be compatible with para_env
      53              : !> \param descriptor the scalapack descriptor of the matrices, when using
      54              : !>        scalapack (ncol_block=descriptor(6), ncol_global=descriptor(4),
      55              : !>        nrow_block=descriptor(5), nrow_global=descriptor(3))
      56              : !> \param ncol_block number of columns of a scalapack block
      57              : !> \param nrow_block number of rows of a scalapack block
      58              : !> \param nrow_global number of rows of the matrix
      59              : !> \param ncol_global number of rows
      60              : !> \param first_p_pos position of the first processor (for scalapack)
      61              : !> \param row_indices real (global) indices of the rows (defined only for
      62              : !>        the local rows really used)
      63              : !> \param col_indices real (global) indices of the cols (defined only for
      64              : !>        the local cols really used)
      65              : !> \param nrow_locals nrow_locals(i) number of local rows of the matrix really
      66              : !>        used on the processors with context%mepos(1)==i
      67              : !> \param ncol_locals ncol_locals(i) number of local rows of the matrix really
      68              : !>        used on the processors with context%mepos(2)==i
      69              : !> \param ref_count reference count (see doc/ReferenceCounting.html)
      70              : !> \param local_leading_dimension leading dimension of the data that is
      71              : !>        stored on this processor
      72              : !>
      73              : !>      readonly attributes:
      74              : !> \param nrow_local number of local rows really used on the actual processor
      75              : !> \param ncol_local number of local cols really used on the actual processor
      76              : !> \note
      77              : !>      use cp_fm_struct_get to extract information from this structure
      78              : !> \par History
      79              : !>      08.2002 created [fawzi]
      80              : !> \author Fawzi Mohamed
      81              : ! **************************************************************************************************
      82              :    TYPE cp_fm_struct_type
      83              :       TYPE(mp_para_env_type), POINTER :: para_env => NULL()
      84              :       TYPE(cp_blacs_env_type), POINTER :: context => NULL()
      85              :       INTEGER, DIMENSION(9) :: descriptor = -1
      86              :       INTEGER :: nrow_block = -1, ncol_block = -1, nrow_global = -1, ncol_global = -1
      87              :       INTEGER, DIMENSION(2) :: first_p_pos = -1
      88              :       INTEGER, DIMENSION(:), POINTER :: row_indices => NULL(), col_indices => NULL(), &
      89              :                                         nrow_locals => NULL(), ncol_locals => NULL()
      90              :       INTEGER :: ref_count = -1, local_leading_dimension = -1
      91              :    CONTAINS
      92              :       PROCEDURE, PASS(struct), NON_OVERRIDABLE :: g2p_row => cp_fm_indxg2p_row
      93              :       PROCEDURE, PASS(struct), NON_OVERRIDABLE :: g2p_col => cp_fm_indxg2p_col
      94              :       PROCEDURE, PASS(struct), NON_OVERRIDABLE :: g2l_row => cp_fm_indxg2l_row
      95              :       PROCEDURE, PASS(struct), NON_OVERRIDABLE :: g2l_col => cp_fm_indxg2l_col
      96              :       PROCEDURE, PASS(struct), NON_OVERRIDABLE :: l2g_row => cp_fm_indxl2g_row
      97              :       PROCEDURE, PASS(struct), NON_OVERRIDABLE :: l2g_col => cp_fm_indxl2g_col
      98              :    END TYPE cp_fm_struct_type
      99              : ! **************************************************************************************************
     100              :    TYPE cp_fm_struct_p_type
     101              :       TYPE(cp_fm_struct_type), POINTER :: struct => NULL()
     102              :    END TYPE cp_fm_struct_p_type
     103              : 
     104              : CONTAINS
     105              : 
     106              : ! **************************************************************************************************
     107              : !> \brief allocates and initializes a full matrix structure
     108              : !> \param fmstruct the pointer that will point to the new structure
     109              : !> \param para_env the parallel environment
     110              : !> \param context the blacs context of this matrix
     111              : !> \param nrow_global the number of row of the full matrix
     112              : !> \param ncol_global the number of columns of the full matrix
     113              : !> \param nrow_block the number of rows of a block of the matrix,
     114              : !>        omit or set to -1 to use the built-in defaults
     115              : !> \param ncol_block the number of columns of a block of the matrix,
     116              : !>        omit or set to -1 to use the built-in defaults
     117              : !> \param descriptor the scalapack descriptor of the matrix (if not given
     118              : !>        a new one is allocated
     119              : !> \param first_p_pos ...
     120              : !> \param local_leading_dimension the leading dimension of the locally stored
     121              : !>        data block
     122              : !> \param template_fmstruct a matrix structure where to take the default values
     123              : !> \param square_blocks ...
     124              : !> \param force_block ...
     125              : !> \par History
     126              : !>      08.2002 created [fawzi]
     127              : !> \author Fawzi Mohamed
     128              : ! **************************************************************************************************
     129       705293 :    SUBROUTINE cp_fm_struct_create(fmstruct, para_env, context, nrow_global, &
     130              :                                   ncol_global, nrow_block, ncol_block, descriptor, first_p_pos, &
     131              :                                   local_leading_dimension, template_fmstruct, square_blocks, force_block)
     132              : 
     133              :       TYPE(cp_fm_struct_type), POINTER             :: fmstruct
     134              :       TYPE(mp_para_env_type), TARGET, OPTIONAL     :: para_env
     135              :       INTEGER, INTENT(in), OPTIONAL                :: nrow_global, ncol_global
     136              :       INTEGER, INTENT(in), OPTIONAL                :: nrow_block, ncol_block
     137              :       INTEGER, INTENT(in), OPTIONAL                :: local_leading_dimension
     138              :       TYPE(cp_blacs_env_type), TARGET, OPTIONAL    :: context
     139              :       INTEGER, DIMENSION(9), INTENT(in), OPTIONAL  :: descriptor
     140              :       INTEGER, OPTIONAL, DIMENSION(2)              :: first_p_pos
     141              :       TYPE(cp_fm_struct_type), TARGET, OPTIONAL    :: template_fmstruct
     142              :       LOGICAL, OPTIONAL, INTENT(in)                :: square_blocks
     143              :       LOGICAL, OPTIONAL, INTENT(in)                :: force_block
     144              : 
     145              :       INTEGER                                      :: i, nmax_block, vlen
     146              : #if defined(__parallel)
     147              :       INTEGER                                      :: iunit, stat
     148              :       INTEGER, EXTERNAL                            :: numroc
     149              :       TYPE(cp_logger_type), POINTER                :: logger
     150              : #endif
     151              : 
     152              :       LOGICAL :: my_square_blocks, my_force_block
     153              : 
     154      8463516 :       ALLOCATE (fmstruct)
     155              : 
     156       705293 :       IF (.NOT. PRESENT(template_fmstruct)) THEN
     157       535953 :          CPASSERT(PRESENT(context))
     158       535953 :          CPASSERT(PRESENT(nrow_global))
     159       535953 :          CPASSERT(PRESENT(ncol_global))
     160       535953 :          fmstruct%local_leading_dimension = 1
     161       535953 :          fmstruct%nrow_block = 0 ! populate default later
     162       535953 :          fmstruct%ncol_block = 0 ! populate default later
     163              :       ELSE
     164       169340 :          fmstruct%context => template_fmstruct%context
     165       169340 :          fmstruct%para_env => template_fmstruct%para_env
     166      3217460 :          fmstruct%descriptor = template_fmstruct%descriptor
     167       169340 :          fmstruct%nrow_block = template_fmstruct%nrow_block
     168       169340 :          fmstruct%nrow_global = template_fmstruct%nrow_global
     169       169340 :          fmstruct%ncol_block = template_fmstruct%ncol_block
     170       169340 :          fmstruct%ncol_global = template_fmstruct%ncol_global
     171       846700 :          fmstruct%first_p_pos = template_fmstruct%first_p_pos
     172              :          fmstruct%local_leading_dimension = &
     173       169340 :             template_fmstruct%local_leading_dimension
     174              :       END IF
     175              : 
     176              :       ! allow to request default block size (zero or negative value)
     177       705293 :       IF (PRESENT(nrow_block)) fmstruct%nrow_block = nrow_block
     178       705293 :       IF (PRESENT(ncol_block)) fmstruct%ncol_block = ncol_block
     179       705293 :       IF (0 >= fmstruct%nrow_block) THEN
     180       524166 :          fmstruct%nrow_block = optimal_blacs_row_block_size
     181              :       END IF
     182       705293 :       IF (0 >= fmstruct%ncol_block) THEN
     183       515886 :          fmstruct%ncol_block = optimal_blacs_col_block_size
     184              :       END IF
     185       705293 :       CPASSERT(0 < fmstruct%nrow_block .AND. 0 < fmstruct%ncol_block)
     186              : 
     187       705293 :       IF (PRESENT(context)) THEN
     188       542779 :          fmstruct%context => context
     189       542779 :          fmstruct%para_env => context%para_env
     190              :       END IF
     191       705293 :       IF (PRESENT(para_env)) fmstruct%para_env => para_env
     192       705293 :       CALL fmstruct%context%retain()
     193       705293 :       CALL fmstruct%para_env%retain()
     194              : 
     195       705293 :       IF (PRESENT(nrow_global)) THEN
     196       695433 :          fmstruct%nrow_global = nrow_global
     197       695433 :          fmstruct%local_leading_dimension = 1
     198              :       END IF
     199       705293 :       IF (PRESENT(ncol_global)) THEN
     200       703043 :          fmstruct%ncol_global = ncol_global
     201              :       END IF
     202              : 
     203       705293 :       my_force_block = force_block_size
     204       705293 :       IF (PRESENT(force_block)) my_force_block = force_block
     205       705293 :       IF (.NOT. my_force_block) THEN
     206       690528 :          vlen = m_cpuid_vlen()
     207              :          nmax_block = (fmstruct%nrow_global + fmstruct%context%num_pe(1) - 1)/ &
     208       690528 :                       (fmstruct%context%num_pe(1))
     209       690528 :          IF (1 < vlen) THEN ! flooring not ceiling (OOB)
     210       690528 :             fmstruct%nrow_block = fmstruct%nrow_block/vlen*vlen
     211       690528 :             nmax_block = nmax_block/vlen*vlen
     212              :          END IF
     213       690528 :          fmstruct%nrow_block = MAX(MIN(fmstruct%nrow_block, nmax_block), 1)
     214              : 
     215              :          nmax_block = (fmstruct%ncol_global + fmstruct%context%num_pe(2) - 1)/ &
     216       690528 :                       (fmstruct%context%num_pe(2))
     217       690528 :          IF (1 < vlen) THEN ! flooring not ceiling (OOB)
     218       690528 :             fmstruct%ncol_block = fmstruct%ncol_block/vlen*vlen
     219       690528 :             nmax_block = nmax_block/vlen*vlen
     220              :          END IF
     221       690528 :          fmstruct%ncol_block = MAX(MIN(fmstruct%ncol_block, nmax_block), 1)
     222              :       END IF
     223              : 
     224              :       ! square matrix -> square blocks (otherwise, e.g., PDPOTRF fails)
     225       705293 :       my_square_blocks = fmstruct%nrow_global == fmstruct%ncol_global
     226              :       ! however, requesting non-square blocks takes precedence
     227       705293 :       IF (PRESENT(square_blocks)) my_square_blocks = square_blocks
     228       705293 :       IF (my_square_blocks) THEN
     229       459616 :          fmstruct%nrow_block = MIN(fmstruct%nrow_block, fmstruct%ncol_block)
     230       459616 :          fmstruct%ncol_block = fmstruct%nrow_block
     231              :       END IF
     232              : 
     233              :       ALLOCATE (fmstruct%nrow_locals(0:(fmstruct%context%num_pe(1) - 1)), &
     234      3526465 :                 fmstruct%ncol_locals(0:(fmstruct%context%num_pe(2) - 1)))
     235       705293 :       IF (.NOT. PRESENT(template_fmstruct)) THEN
     236      1607859 :          fmstruct%first_p_pos = [0, 0]
     237              :       END IF
     238       705293 :       IF (PRESENT(first_p_pos)) fmstruct%first_p_pos = first_p_pos
     239              : 
     240      1962526 :       fmstruct%nrow_locals = 0
     241      1410586 :       fmstruct%ncol_locals = 0
     242              : #if defined(__parallel)
     243              :       fmstruct%nrow_locals(fmstruct%context%mepos(1)) = &
     244              :          numroc(fmstruct%nrow_global, fmstruct%nrow_block, &
     245              :                 fmstruct%context%mepos(1), fmstruct%first_p_pos(1), &
     246       705293 :                 fmstruct%context%num_pe(1))
     247              :       fmstruct%ncol_locals(fmstruct%context%mepos(2)) = &
     248              :          numroc(fmstruct%ncol_global, fmstruct%ncol_block, &
     249              :                 fmstruct%context%mepos(2), fmstruct%first_p_pos(2), &
     250       705293 :                 fmstruct%context%num_pe(2))
     251      3219759 :       CALL fmstruct%para_env%sum(fmstruct%nrow_locals)
     252      2115879 :       CALL fmstruct%para_env%sum(fmstruct%ncol_locals)
     253      1962526 :       fmstruct%nrow_locals(:) = fmstruct%nrow_locals(:)/fmstruct%context%num_pe(2)
     254      1410586 :       fmstruct%ncol_locals(:) = fmstruct%ncol_locals(:)/fmstruct%context%num_pe(1)
     255              : 
     256      2667819 :       IF (SUM(fmstruct%ncol_locals) /= fmstruct%ncol_global .OR. &
     257              :           SUM(fmstruct%nrow_locals) /= fmstruct%nrow_global) THEN
     258              :          ! try to collect some output if this is going to happen again
     259              :          ! this seems to trigger on blanc, but should really never happen
     260            0 :          logger => cp_get_default_logger()
     261            0 :          iunit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     262            0 :          WRITE (iunit, *) "mepos", fmstruct%context%mepos(1:2), "numpe", fmstruct%context%num_pe(1:2)
     263            0 :          WRITE (iunit, *) "ncol_global", fmstruct%ncol_global
     264            0 :          WRITE (iunit, *) "nrow_global", fmstruct%nrow_global
     265            0 :          WRITE (iunit, *) "ncol_locals", fmstruct%ncol_locals
     266            0 :          WRITE (iunit, *) "nrow_locals", fmstruct%nrow_locals
     267            0 :          CALL m_flush(iunit)
     268              :       END IF
     269              : 
     270      1410586 :       IF (SUM(fmstruct%ncol_locals) /= fmstruct%ncol_global) THEN
     271            0 :          CPABORT("sum of local cols not equal global cols")
     272              :       END IF
     273      1962526 :       IF (SUM(fmstruct%nrow_locals) /= fmstruct%nrow_global) THEN
     274            0 :          CPABORT("sum of local row not equal global rows")
     275              :       END IF
     276              : #else
     277              :       ! block = full matrix
     278              :       fmstruct%nrow_block = fmstruct%nrow_global
     279              :       fmstruct%ncol_block = fmstruct%ncol_global
     280              :       fmstruct%nrow_locals(fmstruct%context%mepos(1)) = fmstruct%nrow_global
     281              :       fmstruct%ncol_locals(fmstruct%context%mepos(2)) = fmstruct%ncol_global
     282              : #endif
     283              : 
     284              :       fmstruct%local_leading_dimension = MAX(fmstruct%local_leading_dimension, &
     285       705293 :                                              fmstruct%nrow_locals(fmstruct%context%mepos(1)))
     286       705293 :       IF (PRESENT(local_leading_dimension)) THEN
     287            0 :          IF (MAX(1, fmstruct%nrow_locals(fmstruct%context%mepos(1))) > local_leading_dimension) THEN
     288              :             CALL cp_abort(__LOCATION__, "local_leading_dimension too small ("// &
     289              :                           cp_to_string(local_leading_dimension)//"<"// &
     290            0 :                           cp_to_string(fmstruct%local_leading_dimension)//")")
     291              :          END IF
     292            0 :          fmstruct%local_leading_dimension = local_leading_dimension
     293              :       END IF
     294              : 
     295       705293 :       NULLIFY (fmstruct%row_indices, fmstruct%col_indices)
     296              : 
     297              :       ! the max should go away
     298      2115879 :       ALLOCATE (fmstruct%row_indices(MAX(fmstruct%nrow_locals(fmstruct%context%mepos(1)), 1)))
     299      7781414 :       DO i = 1, SIZE(fmstruct%row_indices)
     300              : #ifdef __parallel
     301      7781414 :          fmstruct%row_indices(i) = fmstruct%l2g_row(i, fmstruct%context%mepos(1))
     302              : #else
     303              :          fmstruct%row_indices(i) = i
     304              : #endif
     305              :       END DO
     306      2115879 :       ALLOCATE (fmstruct%col_indices(MAX(fmstruct%ncol_locals(fmstruct%context%mepos(2)), 1)))
     307      8584518 :       DO i = 1, SIZE(fmstruct%col_indices)
     308              : #ifdef __parallel
     309      8584518 :          fmstruct%col_indices(i) = fmstruct%l2g_col(i, fmstruct%context%mepos(2))
     310              : #else
     311              :          fmstruct%col_indices(i) = i
     312              : #endif
     313              :       END DO
     314              : 
     315       705293 :       fmstruct%ref_count = 1
     316              : 
     317       705293 :       IF (PRESENT(descriptor)) THEN
     318            0 :          fmstruct%descriptor = descriptor
     319              :       ELSE
     320      7052930 :          fmstruct%descriptor = 0
     321              : #if defined(__parallel)
     322              :          ! local leading dimension needs to be at least 1
     323              :          CALL descinit(fmstruct%descriptor, fmstruct%nrow_global, &
     324              :                        fmstruct%ncol_global, fmstruct%nrow_block, &
     325              :                        fmstruct%ncol_block, fmstruct%first_p_pos(1), &
     326              :                        fmstruct%first_p_pos(2), fmstruct%context, &
     327       705293 :                        fmstruct%local_leading_dimension, stat)
     328       705293 :          CPASSERT(stat == 0)
     329              : #endif
     330              :       END IF
     331       705293 :    END SUBROUTINE cp_fm_struct_create
     332              : 
     333              : ! **************************************************************************************************
     334              : !> \brief retains a full matrix structure
     335              : !> \param fmstruct the structure to retain
     336              : !> \par History
     337              : !>      08.2002 created [fawzi]
     338              : !> \author Fawzi Mohamed
     339              : ! **************************************************************************************************
     340      2465552 :    SUBROUTINE cp_fm_struct_retain(fmstruct)
     341              :       TYPE(cp_fm_struct_type), INTENT(INOUT)             :: fmstruct
     342              : 
     343      2465552 :       CPASSERT(fmstruct%ref_count > 0)
     344      2465552 :       fmstruct%ref_count = fmstruct%ref_count + 1
     345      2465552 :    END SUBROUTINE cp_fm_struct_retain
     346              : 
     347              : ! **************************************************************************************************
     348              : !> \brief releases a full matrix structure
     349              : !> \param fmstruct the structure to release
     350              : !> \par History
     351              : !>      08.2002 created [fawzi]
     352              : !> \author Fawzi Mohamed
     353              : ! **************************************************************************************************
     354      3216200 :    SUBROUTINE cp_fm_struct_release(fmstruct)
     355              :       TYPE(cp_fm_struct_type), POINTER                   :: fmstruct
     356              : 
     357      3216200 :       IF (ASSOCIATED(fmstruct)) THEN
     358      3170837 :          CPASSERT(fmstruct%ref_count > 0)
     359      3170837 :          fmstruct%ref_count = fmstruct%ref_count - 1
     360      3170837 :          IF (fmstruct%ref_count < 1) THEN
     361       705285 :             CALL cp_blacs_env_release(fmstruct%context)
     362       705285 :             CALL mp_para_env_release(fmstruct%para_env)
     363       705285 :             IF (ASSOCIATED(fmstruct%row_indices)) THEN
     364       705285 :                DEALLOCATE (fmstruct%row_indices)
     365              :             END IF
     366       705285 :             IF (ASSOCIATED(fmstruct%col_indices)) THEN
     367       705285 :                DEALLOCATE (fmstruct%col_indices)
     368              :             END IF
     369       705285 :             IF (ASSOCIATED(fmstruct%nrow_locals)) THEN
     370       705285 :                DEALLOCATE (fmstruct%nrow_locals)
     371              :             END IF
     372       705285 :             IF (ASSOCIATED(fmstruct%ncol_locals)) THEN
     373       705285 :                DEALLOCATE (fmstruct%ncol_locals)
     374              :             END IF
     375       705285 :             DEALLOCATE (fmstruct)
     376              :          END IF
     377              :       END IF
     378      3216200 :       NULLIFY (fmstruct)
     379      3216200 :    END SUBROUTINE cp_fm_struct_release
     380              : 
     381              : ! **************************************************************************************************
     382              : !> \brief returns true if the two matrix structures are equivalent, false
     383              : !>      otherwise.
     384              : !> \param fmstruct1 one of the full matrix structures to compare
     385              : !> \param fmstruct2 the second of the full matrix structures to compare
     386              : !> \return ...
     387              : !> \par History
     388              : !>      08.2002 created [fawzi]
     389              : !> \author Fawzi Mohamed
     390              : ! **************************************************************************************************
     391      4707567 :    FUNCTION cp_fm_struct_equivalent(fmstruct1, fmstruct2) RESULT(res)
     392              :       TYPE(cp_fm_struct_type), POINTER                   :: fmstruct1, fmstruct2
     393              :       LOGICAL                                            :: res
     394              : 
     395              :       INTEGER                                            :: i
     396              : 
     397      4707567 :       CPASSERT(ASSOCIATED(fmstruct1))
     398      4707567 :       CPASSERT(ASSOCIATED(fmstruct2))
     399      4707567 :       CPASSERT(fmstruct1%ref_count > 0)
     400      4707567 :       CPASSERT(fmstruct2%ref_count > 0)
     401      4707567 :       IF (ASSOCIATED(fmstruct1, fmstruct2)) THEN
     402              :          res = .TRUE.
     403              :       ELSE
     404              :          res = (fmstruct1%context == fmstruct2%context) .AND. &
     405              :                (fmstruct1%nrow_global == fmstruct2%nrow_global) .AND. &
     406              :                (fmstruct1%ncol_global == fmstruct2%ncol_global) .AND. &
     407              :                (fmstruct1%nrow_block == fmstruct2%nrow_block) .AND. &
     408              :                (fmstruct1%ncol_block == fmstruct2%ncol_block) .AND. &
     409              :                (fmstruct1%local_leading_dimension == &
     410       337263 :                 fmstruct2%local_leading_dimension)
     411      3372630 :          DO i = 1, 9
     412      3372630 :             res = res .AND. (fmstruct1%descriptor(i) == fmstruct1%descriptor(i))
     413              :          END DO
     414              :       END IF
     415      4707567 :    END FUNCTION cp_fm_struct_equivalent
     416              : 
     417              : ! **************************************************************************************************
     418              : !> \brief returns the values of various attributes of the matrix structure
     419              : !> \param fmstruct the structure you want info about
     420              : !> \param para_env ...
     421              : !> \param context ...
     422              : !> \param descriptor ...
     423              : !> \param ncol_block ...
     424              : !> \param nrow_block ...
     425              : !> \param nrow_global ...
     426              : !> \param ncol_global ...
     427              : !> \param first_p_pos ...
     428              : !> \param row_indices ...
     429              : !> \param col_indices ...
     430              : !> \param nrow_local ...
     431              : !> \param ncol_local ...
     432              : !> \param nrow_locals ...
     433              : !> \param ncol_locals ...
     434              : !> \param local_leading_dimension ...
     435              : !> \par History
     436              : !>      08.2002 created [fawzi]
     437              : !> \author Fawzi Mohamed
     438              : ! **************************************************************************************************
     439      9198552 :    SUBROUTINE cp_fm_struct_get(fmstruct, para_env, context, &
     440              :                                descriptor, ncol_block, nrow_block, nrow_global, &
     441              :                                ncol_global, first_p_pos, row_indices, &
     442              :                                col_indices, nrow_local, ncol_local, nrow_locals, ncol_locals, &
     443              :                                local_leading_dimension)
     444              :       TYPE(cp_fm_struct_type), INTENT(IN)                :: fmstruct
     445              :       TYPE(mp_para_env_type), OPTIONAL, POINTER          :: para_env
     446              :       TYPE(cp_blacs_env_type), OPTIONAL, POINTER         :: context
     447              :       INTEGER, DIMENSION(9), INTENT(OUT), OPTIONAL       :: descriptor
     448              :       INTEGER, INTENT(out), OPTIONAL                     :: ncol_block, nrow_block, nrow_global, &
     449              :                                                             ncol_global
     450              :       INTEGER, DIMENSION(2), INTENT(out), OPTIONAL       :: first_p_pos
     451              :       INTEGER, DIMENSION(:), OPTIONAL, POINTER           :: row_indices, col_indices
     452              :       INTEGER, INTENT(out), OPTIONAL                     :: nrow_local, ncol_local
     453              :       INTEGER, DIMENSION(:), OPTIONAL, POINTER           :: nrow_locals, ncol_locals
     454              :       INTEGER, INTENT(out), OPTIONAL                     :: local_leading_dimension
     455              : 
     456      9198552 :       IF (PRESENT(para_env)) para_env => fmstruct%para_env
     457      9198552 :       IF (PRESENT(context)) context => fmstruct%context
     458      9198552 :       IF (PRESENT(descriptor)) descriptor = fmstruct%descriptor
     459      9198552 :       IF (PRESENT(ncol_block)) ncol_block = fmstruct%ncol_block
     460      9198552 :       IF (PRESENT(nrow_block)) nrow_block = fmstruct%nrow_block
     461      9198552 :       IF (PRESENT(nrow_global)) nrow_global = fmstruct%nrow_global
     462      9198552 :       IF (PRESENT(ncol_global)) ncol_global = fmstruct%ncol_global
     463      9198552 :       IF (PRESENT(first_p_pos)) first_p_pos = fmstruct%first_p_pos
     464      9198552 :       IF (PRESENT(nrow_locals)) nrow_locals => fmstruct%nrow_locals
     465      9198552 :       IF (PRESENT(ncol_locals)) ncol_locals => fmstruct%ncol_locals
     466      9198552 :       IF (PRESENT(local_leading_dimension)) local_leading_dimension = &
     467        10183 :          fmstruct%local_leading_dimension
     468              : 
     469      9198552 :       IF (PRESENT(nrow_local)) nrow_local = fmstruct%nrow_locals(fmstruct%context%mepos(1))
     470      9198552 :       IF (PRESENT(ncol_local)) ncol_local = fmstruct%ncol_locals(fmstruct%context%mepos(2))
     471              : 
     472      9198552 :       IF (PRESENT(row_indices)) row_indices => fmstruct%row_indices
     473      9198552 :       IF (PRESENT(col_indices)) col_indices => fmstruct%col_indices
     474      9198552 :    END SUBROUTINE cp_fm_struct_get
     475              : 
     476              : ! **************************************************************************************************
     477              : !> \brief Write nicely formatted info about the FM struct to the given I/O unit
     478              : !> \param fmstruct a cp_fm_struct_type instance
     479              : !> \param io_unit the I/O unit to use for writing
     480              : ! **************************************************************************************************
     481            3 :    SUBROUTINE cp_fm_struct_write_info(fmstruct, io_unit)
     482              :       TYPE(cp_fm_struct_type), INTENT(IN)                :: fmstruct
     483              :       INTEGER, INTENT(IN)                                :: io_unit
     484              : 
     485              :       INTEGER, PARAMETER                                 :: oblock_size = 8
     486              : 
     487              :       CHARACTER(len=30)                                  :: fm
     488              :       INTEGER                                            :: oblock
     489              : 
     490            3 :       WRITE (fm, "(A,I2,A)") "(A,I5,A,I5,A,", oblock_size, "I6)"
     491              : 
     492            3 :       WRITE (io_unit, '(A,I12)') "CP_FM_STRUCT | No. of matrix columns:   ", fmstruct%ncol_global
     493            3 :       WRITE (io_unit, '(A,I12)') "CP_FM_STRUCT | No. of matrix rows:      ", fmstruct%nrow_global
     494            3 :       WRITE (io_unit, '(A,I12)') "CP_FM_STRUCT | No. of block columns:    ", fmstruct%ncol_block
     495            3 :       WRITE (io_unit, '(A,I12)') "CP_FM_STRUCT | No. of block rows:       ", fmstruct%nrow_block
     496              : 
     497            3 :       WRITE (io_unit, '(A)') "CP_FM_STRUCT | Number of local columns: "
     498            6 :       DO oblock = 0, (SIZE(fmstruct%ncol_locals) - 1)/oblock_size
     499            3 :          WRITE (io_unit, fm) "CP_FM_STRUCT | CPUs ", &
     500            3 :             oblock*oblock_size, "..", (oblock + 1)*oblock_size - 1, ": ", &
     501            9 :             fmstruct%ncol_locals(oblock*oblock_size:MIN(SIZE(fmstruct%ncol_locals), (oblock + 1)*oblock_size) - 1)
     502              :       END DO
     503              : 
     504            3 :       WRITE (io_unit, '(A)') "CP_FM_STRUCT | Number of local rows:    "
     505            6 :       DO oblock = 0, (SIZE(fmstruct%nrow_locals) - 1)/oblock_size
     506            3 :          WRITE (io_unit, fm) "CP_FM_STRUCT | CPUs ", &
     507            3 :             oblock*oblock_size, "..", (oblock + 1)*oblock_size - 1, ": ", &
     508            9 :             fmstruct%nrow_locals(oblock*oblock_size:MIN(SIZE(fmstruct%nrow_locals), (oblock + 1)*oblock_size) - 1)
     509              :       END DO
     510            3 :    END SUBROUTINE cp_fm_struct_write_info
     511              : 
     512              : ! **************************************************************************************************
     513              : !> \brief creates a struct with twice the number of blocks on each core.
     514              : !>        If matrix A has to be multiplied with B anc C, a
     515              : !>        significant speedup of pdgemm can be acchieved by joining the matrices
     516              : !>        in a new one with this structure (see arnoldi in rt_matrix_exp)
     517              : !> \param fmstruct the struct to create
     518              : !> \param struct struct of either A or B
     519              : !> \param context ...
     520              : !> \param col in which direction the matrix should be enlarged
     521              : !> \param row in which direction the matrix should be enlarged
     522              : !> \par History
     523              : !>      06.2009 created [fschiff]
     524              : !> \author Florian Schiffmann
     525              : ! **************************************************************************************************
     526         5318 :    SUBROUTINE cp_fm_struct_double(fmstruct, struct, context, col, row)
     527              :       TYPE(cp_fm_struct_type), POINTER                   :: fmstruct
     528              :       TYPE(cp_fm_struct_type), INTENT(INOUT)             :: struct
     529              :       TYPE(cp_blacs_env_type), INTENT(INOUT), TARGET     :: context
     530              :       LOGICAL, INTENT(in)                                :: col, row
     531              : 
     532              :       INTEGER :: n_doubled_items_in_partially_filled_block, ncol_block, ncol_global, newdim_col, &
     533              :          newdim_row, nfilled_blocks, nfilled_blocks_remain, nprocs_col, nprocs_row, nrow_block, &
     534              :          nrow_global
     535              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     536              : 
     537              :       CALL cp_fm_struct_get(struct, nrow_global=nrow_global, &
     538              :                             ncol_global=ncol_global, nrow_block=nrow_block, &
     539         5318 :                             ncol_block=ncol_block)
     540         5318 :       newdim_row = nrow_global
     541         5318 :       newdim_col = ncol_global
     542         5318 :       nprocs_row = context%num_pe(1)
     543         5318 :       nprocs_col = context%num_pe(2)
     544         5318 :       para_env => struct%para_env
     545              : 
     546         5318 :       IF (col) THEN
     547         5318 :          IF (ncol_global == 0) THEN
     548          120 :             newdim_col = 0
     549              :          ELSE
     550              :             ! ncol_block            nfilled_blocks_remain * ncol_block
     551              :             !     |<--->|           |<--->|
     552              :             !     |-----|-----|-----|-----|---|
     553              :             !     |  0  |  1  |  2  |  0  | 1 | <- context%mepos(2)
     554              :             !     |-----|-----|-----|-----|---|
     555              :             !     |<--- nfilled_blocks -->|<->  -- items (columns) in partially filled blocks
     556              :             !     |     * ncol_block      |
     557         5198 :             n_doubled_items_in_partially_filled_block = 2*MOD(ncol_global, ncol_block)
     558         5198 :             nfilled_blocks = ncol_global/ncol_block
     559         5198 :             nfilled_blocks_remain = MOD(nfilled_blocks, nprocs_col)
     560         5198 :             newdim_col = 2*(nfilled_blocks/nprocs_col)
     561         5198 :             IF (n_doubled_items_in_partially_filled_block > ncol_block) THEN
     562              :                ! doubled number of columns in a partially filled block does not fit into a single block.
     563              :                ! Due to cyclic distribution of ScaLAPACK blocks, an extra block for each core needs to be added
     564              :                ! |-----|-----|-----|----|     |-----|-----|-----|-----|-----|-----|-----|-----|-----|---|
     565              :                ! |  0  |  1  |  2  |  0 | --> |  0  |  1  |  2  |  0  |  1  |  2  |  0  |  1  |  2  |  0|
     566              :                ! |-----|-----|-----|----|     |-----|-----|-----|-----|-----|-----|-----|-----|-----|---|
     567              :                !    a     a     a     b          a1    a1    a1    a2    a2    a2    b1  empty empty  b2
     568            0 :                newdim_col = newdim_col + 1
     569              : 
     570              :                ! the number of columns which does not fit into the added extra block
     571            0 :                n_doubled_items_in_partially_filled_block = n_doubled_items_in_partially_filled_block - ncol_block
     572         5198 :             ELSE IF (nfilled_blocks_remain > 0) THEN
     573              :                ! |-----|-----|-----|-----|--|    |-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|
     574              :                ! |  0  |  1  |  2  |  0  | 1| -> |  0  |  1  |  2  |  0  |  1  |  2  |  0  |  1  |  2  |  0  |
     575              :                ! |-----|-----|-----|-----|--|    |-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|
     576              :                !    a     a     a     b    b        a1    a1    a1    a2    a2    a2    b1  b1 b2 empty   b2
     577            0 :                newdim_col = newdim_col + 1
     578            0 :                n_doubled_items_in_partially_filled_block = 0
     579              :             END IF
     580              : 
     581         5198 :             newdim_col = (newdim_col*nprocs_col + nfilled_blocks_remain)*ncol_block + n_doubled_items_in_partially_filled_block
     582              :          END IF
     583              :       END IF
     584              : 
     585         5318 :       IF (row) THEN
     586            0 :          IF (nrow_global == 0) THEN
     587            0 :             newdim_row = 0
     588              :          ELSE
     589            0 :             n_doubled_items_in_partially_filled_block = 2*MOD(nrow_global, nrow_block)
     590            0 :             nfilled_blocks = nrow_global/nrow_block
     591            0 :             nfilled_blocks_remain = MOD(nfilled_blocks, nprocs_row)
     592            0 :             newdim_row = 2*(nfilled_blocks/nprocs_row)
     593            0 :             IF (n_doubled_items_in_partially_filled_block > nrow_block) THEN
     594            0 :                newdim_row = newdim_row + 1
     595            0 :                n_doubled_items_in_partially_filled_block = n_doubled_items_in_partially_filled_block - nrow_block
     596            0 :             ELSE IF (nfilled_blocks_remain > 0) THEN
     597            0 :                newdim_row = newdim_row + 1
     598            0 :                n_doubled_items_in_partially_filled_block = 0
     599              :             END IF
     600              : 
     601            0 :             newdim_row = (newdim_row*nprocs_row + nfilled_blocks_remain)*nrow_block + n_doubled_items_in_partially_filled_block
     602              :          END IF
     603              :       END IF
     604              : 
     605              :       ! square_blocks=.FALSE. ensures that matrix blocks of the doubled matrix will have
     606              :       ! nrow_block x ncol_block shape even in case of a square doubled matrix
     607              :       CALL cp_fm_struct_create(fmstruct=fmstruct, para_env=para_env, &
     608              :                                context=context, &
     609              :                                nrow_global=newdim_row, &
     610              :                                ncol_global=newdim_col, &
     611              :                                ncol_block=ncol_block, &
     612              :                                nrow_block=nrow_block, &
     613         5318 :                                square_blocks=.FALSE.)
     614              : 
     615         5318 :    END SUBROUTINE cp_fm_struct_double
     616              : ! **************************************************************************************************
     617              : !> \brief allows to modify the default settings for matrix creation
     618              : !> \param nrow_block ...
     619              : !> \param ncol_block ...
     620              : !> \param force_block ...
     621              : ! **************************************************************************************************
     622        11087 :    SUBROUTINE cp_fm_struct_config(nrow_block, ncol_block, force_block)
     623              :       INTEGER, INTENT(IN), OPTIONAL                      :: nrow_block, ncol_block
     624              :       LOGICAL, INTENT(IN), OPTIONAL                      :: force_block
     625              : 
     626              :       INTEGER                                            :: vlen
     627              : 
     628        11087 :       vlen = m_cpuid_vlen()
     629        11087 :       IF (PRESENT(ncol_block)) THEN
     630        11087 :          IF (0 < ncol_block) THEN
     631        11087 :             optimal_blacs_col_block_size = (ncol_block + vlen - 1)/vlen*vlen
     632              :          END IF
     633              :       END IF
     634        11087 :       IF (PRESENT(nrow_block)) THEN
     635        11087 :          IF (0 < nrow_block) THEN
     636        11087 :             optimal_blacs_row_block_size = (nrow_block + vlen - 1)/vlen*vlen
     637              :          END IF
     638              :       END IF
     639        11087 :       IF (PRESENT(force_block)) force_block_size = force_block
     640              : 
     641        11087 :    END SUBROUTINE cp_fm_struct_config
     642              : 
     643              : ! **************************************************************************************************
     644              : !> \brief ...
     645              : !> \return ...
     646              : ! **************************************************************************************************
     647        32440 :    FUNCTION cp_fm_struct_get_nrow_block() RESULT(res)
     648              :       INTEGER                                            :: res
     649              : 
     650        32440 :       res = optimal_blacs_row_block_size
     651        32440 :    END FUNCTION cp_fm_struct_get_nrow_block
     652              : 
     653              : ! **************************************************************************************************
     654              : !> \brief ...
     655              : !> \return ...
     656              : ! **************************************************************************************************
     657        32440 :    FUNCTION cp_fm_struct_get_ncol_block() RESULT(res)
     658              :       INTEGER                                            :: res
     659              : 
     660        32440 :       res = optimal_blacs_col_block_size
     661        32440 :    END FUNCTION cp_fm_struct_get_ncol_block
     662              : 
     663              : ! **************************************************************************************************
     664              : !> \brief wrapper to scalapack function INDXG2P that computes the row process
     665              : !>         coordinate which possesses the entry of a distributed matrix specified
     666              : !>         by a global index INDXGLOB.
     667              : !> \param struct ...
     668              : !> \param INDXGLOB ...
     669              : !> \return ...
     670              : !> \author Mauro Del Ben [MDB] - 12.2012, modified by F. Stein
     671              : ! **************************************************************************************************
     672     13294639 :    FUNCTION cp_fm_indxg2p_row(struct, INDXGLOB) RESULT(G2P)
     673              :       CLASS(cp_fm_struct_type), INTENT(IN) :: struct
     674              :       INTEGER, INTENT(IN) :: INDXGLOB
     675              :       INTEGER                                  :: G2P
     676              : 
     677              : #if defined(__parallel)
     678              :       INTEGER :: number_of_process_rows
     679              :       INTEGER, EXTERNAL :: indxg2p
     680              : #endif
     681              : 
     682              : #if defined(__parallel)
     683              : 
     684     13294639 :       CALL struct%context%get(number_of_process_rows=number_of_process_rows)
     685              : 
     686     13294639 :       G2P = indxg2p(INDXGLOB, struct%nrow_block, 0, struct%first_p_pos(1), number_of_process_rows)
     687              : 
     688              : #else
     689              :       MARK_USED(struct)
     690              :       MARK_USED(indxglob)
     691              : 
     692              :       G2P = 0
     693              : 
     694              : #endif
     695              : 
     696     13294639 :    END FUNCTION cp_fm_indxg2p_row
     697              : 
     698              : ! **************************************************************************************************
     699              : !> \brief wrapper to scalapack function INDXG2P that computes the col process
     700              : !>         coordinate which possesses the entry of a distributed matrix specified
     701              : !>         by a global index INDXGLOB.
     702              : !> \param struct ...
     703              : !> \param INDXGLOB ...
     704              : !> \return ...
     705              : !> \author Mauro Del Ben [MDB] - 12.2012, modified by F. Stein
     706              : ! **************************************************************************************************
     707      6864273 :    FUNCTION cp_fm_indxg2p_col(struct, INDXGLOB) RESULT(G2P)
     708              :       CLASS(cp_fm_struct_type), INTENT(IN) :: struct
     709              :       INTEGER, INTENT(IN) :: INDXGLOB
     710              :       INTEGER                                  :: G2P
     711              : 
     712              : #if defined(__parallel)
     713              :       INTEGER :: number_of_process_columns
     714              :       INTEGER, EXTERNAL :: indxg2p
     715              : #endif
     716              : 
     717              : #if defined(__parallel)
     718              : 
     719      6864273 :       CALL struct%context%get(number_of_process_columns=number_of_process_columns)
     720              : 
     721      6864273 :       G2P = indxg2p(INDXGLOB, struct%ncol_block, 0, struct%first_p_pos(2), number_of_process_columns)
     722              : 
     723              : #else
     724              :       MARK_USED(struct)
     725              :       MARK_USED(indxglob)
     726              : 
     727              :       G2P = 0
     728              : 
     729              : #endif
     730              : 
     731      6864273 :    END FUNCTION cp_fm_indxg2p_col
     732              : 
     733              : ! **************************************************************************************************
     734              : !> \brief wrapper to scalapack function INDXG2L that computes the local index
     735              : !>         of a distributed matrix entry pointed to by the global index INDXGLOB.
     736              : !>
     737              : !>  Arguments
     738              : !>  =========
     739              : !>
     740              : !>  INDXGLOB  (global input) INTEGER
     741              : !>            The global index of the distributed matrix entry.
     742              : !>
     743              : !>  NB        (global input) INTEGER
     744              : !>            Block size, size of the blocks the distributed matrix is
     745              : !>            split into.
     746              : !>
     747              : !>  IPROC     (local dummy) INTEGER
     748              : !>            Dummy argument in this case in order to unify the calling
     749              : !>            sequence of the tool-routines.
     750              : !>
     751              : !>  ISRCPROC  (local dummy) INTEGER
     752              : !>            Dummy argument in this case in order to unify the calling
     753              : !>            sequence of the tool-routines.
     754              : !>
     755              : !>  NPROCS    (global input) INTEGER
     756              : !>            The total number processes over which the distributed
     757              : !>            matrix is distributed.
     758              : !>
     759              : !> \param struct ...
     760              : !> \param INDXGLOB ...
     761              : !> \return ...
     762              : !> \author Mauro Del Ben [MDB] - 12.2012
     763              : ! **************************************************************************************************
     764      2595788 :    FUNCTION cp_fm_indxg2l_row(struct, INDXGLOB) RESULT(G2L)
     765              :       CLASS(cp_fm_struct_type), INTENT(IN) :: struct
     766              :       INTEGER, INTENT(IN)                      :: INDXGLOB
     767              :       INTEGER                                  :: G2L
     768              : 
     769              : #if defined(__parallel)
     770              :       INTEGER :: number_of_process_rows
     771              :       INTEGER, EXTERNAL :: indxg2l
     772              : #endif
     773              : 
     774              : #if defined(__parallel)
     775              : 
     776      2595788 :       CALL struct%context%get(number_of_process_rows=number_of_process_rows)
     777              : 
     778      2595788 :       G2L = indxg2l(INDXGLOB, struct%nrow_block, 0, struct%first_p_pos(1), number_of_process_rows)
     779              : 
     780              : #else
     781              :       MARK_USED(struct)
     782              : 
     783              :       G2L = INDXGLOB
     784              : 
     785              : #endif
     786              : 
     787      2595788 :    END FUNCTION cp_fm_indxg2l_row
     788              : 
     789              : ! **************************************************************************************************
     790              : !> \brief wrapper to scalapack function INDXG2L that computes the local index
     791              : !>         of a distributed matrix entry pointed to by the global index INDXGLOB.
     792              : !>
     793              : !>  Arguments
     794              : !>  =========
     795              : !>
     796              : !>  INDXGLOB  (global input) INTEGER
     797              : !>            The global index of the distributed matrix entry.
     798              : !>
     799              : !>  NB        (global input) INTEGER
     800              : !>            Block size, size of the blocks the distributed matrix is
     801              : !>            split into.
     802              : !>
     803              : !>  IPROC     (local dummy) INTEGER
     804              : !>            Dummy argument in this case in order to unify the calling
     805              : !>            sequence of the tool-routines.
     806              : !>
     807              : !>  ISRCPROC  (local dummy) INTEGER
     808              : !>            Dummy argument in this case in order to unify the calling
     809              : !>            sequence of the tool-routines.
     810              : !>
     811              : !>  NPROCS    (global input) INTEGER
     812              : !>            The total number processes over which the distributed
     813              : !>            matrix is distributed.
     814              : !>
     815              : !> \param struct ...
     816              : !> \param INDXGLOB ...
     817              : !> \return ...
     818              : !> \author Mauro Del Ben [MDB] - 12.2012
     819              : ! **************************************************************************************************
     820       493681 :    FUNCTION cp_fm_indxg2l_col(struct, INDXGLOB) RESULT(G2L)
     821              :       CLASS(cp_fm_struct_type), INTENT(IN) :: struct
     822              :       INTEGER, INTENT(IN)                      :: INDXGLOB
     823              :       INTEGER                                  :: G2L
     824              : 
     825              : #if defined(__parallel)
     826              :       INTEGER :: number_of_process_columns
     827              :       INTEGER, EXTERNAL :: indxg2l
     828              : #endif
     829              : 
     830              : #if defined(__parallel)
     831              : 
     832       493681 :       CALL struct%context%get(number_of_process_columns=number_of_process_columns)
     833              : 
     834       493681 :       G2L = indxg2l(INDXGLOB, struct%ncol_block, 0, struct%first_p_pos(2), number_of_process_columns)
     835              : 
     836              : #else
     837              :       MARK_USED(struct)
     838              : 
     839              :       G2L = INDXGLOB
     840              : 
     841              : #endif
     842              : 
     843       493681 :    END FUNCTION cp_fm_indxg2l_col
     844              : 
     845              : ! **************************************************************************************************
     846              : !> \brief wrapper to scalapack function INDXL2G that computes the global index
     847              : !>         of a distributed matrix entry pointed to by the local index INDXLOC
     848              : !>         of the process indicated by IPROC.
     849              : !>
     850              : !>  Arguments
     851              : !>  =========
     852              : !>
     853              : !>  INDXLOC   (global input) INTEGER
     854              : !>            The local index of the distributed matrix entry.
     855              : !>
     856              : !>  NB        (global input) INTEGER
     857              : !>            Block size, size of the blocks the distributed matrix is
     858              : !>            split into.
     859              : !>
     860              : !>  IPROC     (local input) INTEGER
     861              : !>            The coordinate of the process whose local array row or
     862              : !>            column is to be determined.
     863              : !>
     864              : !>  ISRCPROC  (global input) INTEGER
     865              : !>            The coordinate of the process that possesses the first
     866              : !>            row/column of the distributed matrix.
     867              : !>
     868              : !>  NPROCS    (global input) INTEGER
     869              : !>            The total number processes over which the distributed
     870              : !>            matrix is distributed.
     871              : !>
     872              : !> \param struct ...
     873              : !> \param INDXLOC ...
     874              : !> \param IPROC ...
     875              : !> \return ...
     876              : !> \author Mauro Del Ben [MDB] - 12.2012
     877              : ! **************************************************************************************************
     878      7101812 :    FUNCTION cp_fm_indxl2g_row(struct, INDXLOC, IPROC) RESULT(L2G)
     879              :       CLASS(cp_fm_struct_type), INTENT(IN) :: struct
     880              :       INTEGER, INTENT(IN)                      :: INDXLOC, IPROC
     881              :       INTEGER                                  :: L2G
     882              : 
     883              : #if defined(__parallel)
     884              :       INTEGER :: number_of_process_rows
     885              :       INTEGER, EXTERNAL :: indxl2g
     886              : 
     887      7101812 :       CALL struct%context%get(number_of_process_rows=number_of_process_rows)
     888              : 
     889      7101812 :       L2G = indxl2g(INDXLOC, struct%nrow_block, IPROC, struct%first_p_pos(1), number_of_process_rows)
     890              : 
     891              : #else
     892              :       MARK_USED(struct)
     893              :       MARK_USED(indxloc)
     894              :       MARK_USED(iproc)
     895              : 
     896              :       L2G = INDXLOC
     897              : 
     898              : #endif
     899              : 
     900      7101812 :    END FUNCTION cp_fm_indxl2g_row
     901              : 
     902              : ! **************************************************************************************************
     903              : !> \brief wrapper to scalapack function INDXL2G that computes the global index
     904              : !>         of a distributed matrix entry pointed to by the local index INDXLOC
     905              : !>         of the process indicated by IPROC.
     906              : !>
     907              : !>  Arguments
     908              : !>  =========
     909              : !>
     910              : !>  INDXLOC   (global input) INTEGER
     911              : !>            The local index of the distributed matrix entry.
     912              : !>
     913              : !>  NB        (global input) INTEGER
     914              : !>            Block size, size of the blocks the distributed matrix is
     915              : !>            split into.
     916              : !>
     917              : !>  IPROC     (local input) INTEGER
     918              : !>            The coordinate of the process whose local array row or
     919              : !>            column is to be determined.
     920              : !>
     921              : !>  ISRCPROC  (global input) INTEGER
     922              : !>            The coordinate of the process that possesses the first
     923              : !>            row/column of the distributed matrix.
     924              : !>
     925              : !>  NPROCS    (global input) INTEGER
     926              : !>            The total number processes over which the distributed
     927              : !>            matrix is distributed.
     928              : !>
     929              : !> \param struct ...
     930              : !> \param INDXLOC ...
     931              : !> \param IPROC ...
     932              : !> \return ...
     933              : !> \author Mauro Del Ben [MDB] - 12.2012
     934              : ! **************************************************************************************************
     935      7940713 :    FUNCTION cp_fm_indxl2g_col(struct, INDXLOC, IPROC) RESULT(L2G)
     936              :       CLASS(cp_fm_struct_type), INTENT(IN) :: struct
     937              :       INTEGER, INTENT(IN)                      :: INDXLOC, IPROC
     938              :       INTEGER                                  :: L2G
     939              : 
     940              : #if defined(__parallel)
     941              :       INTEGER :: number_of_process_columns
     942              :       INTEGER, EXTERNAL :: indxl2g
     943              : 
     944      7940713 :       CALL struct%context%get(number_of_process_columns=number_of_process_columns)
     945              : 
     946      7940713 :       L2G = indxl2g(INDXLOC, struct%ncol_block, IPROC, struct%first_p_pos(2), number_of_process_columns)
     947              : 
     948              : #else
     949              :       MARK_USED(struct)
     950              :       MARK_USED(indxloc)
     951              :       MARK_USED(iproc)
     952              : 
     953              :       L2G = INDXLOC
     954              : 
     955              : #endif
     956              : 
     957      7940713 :    END FUNCTION cp_fm_indxl2g_col
     958              : 
     959            0 : END MODULE cp_fm_struct
        

Generated by: LCOV version 2.0-1