1C 2C This file is part of MUMPS 5.1.2, released 3C on Mon Oct 2 07:37:01 UTC 2017 4C 5C 6C Copyright 1991-2017 CERFACS, CNRS, ENS Lyon, INP Toulouse, Inria, 7C University of Bordeaux. 8C 9C This version of MUMPS is provided to you free of charge. It is 10C released under the CeCILL-C license: 11C http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html 12C 13C This file contains routines related to OOC, 14C panels, and pivoting. They are used to store 15C permutation information of what is already on 16C disk to be able to permute things back at the 17C solve stage. 18C They do not need to be in the MUMPS_OOC 19C module (most of them do not use any variable 20C from the module, or are called from routines 21C where we do not necessarily want to do a 22C USE DMUMPS_OOC). 23 INTEGER FUNCTION DMUMPS_OOC_GET_PANEL_SIZE 24 & ( HBUF_SIZE, NNMAX, K227, K50 ) 25 IMPLICIT NONE 26C 27C Arguments: 28C ========= 29C 30 INTEGER, INTENT(IN) :: NNMAX, K227, K50 31 INTEGER(8), INTENT(IN) :: HBUF_SIZE 32C 33C Purpose: 34C ======= 35C 36C - Compute the effective size (maximum number of pivots in a panel) 37C for a front with NNMAX entries in its row (for U) / 38C column (for L). 39C - Be able to adapt the fixed number of columns in panel 40C depending on NNMAX, and size of IO buffer HBUF_SIZE 41C 42C Local variables 43C =============== 44C 45 INTEGER K227_LOC 46 INTEGER NBCOL_MAX 47 INTEGER EFFECTIVE_SIZE 48 NBCOL_MAX=int(HBUF_SIZE / int(NNMAX,8)) 49C KEEP(227): Maximum size (nb of col/row) of a panel 50 K227_LOC = abs(K227) 51 IF (K50.EQ.2) THEN 52C for 2x2 pivots we may end-up having the first part 53C of a 2x2 pivot in the last col of the panel; the 54C adopted solution consists in adding the next column 55C to the panel; therefore we need be able to 56C dynamically increase the panel size by one. 57C note that we also maintain property: 58C KEEP(227): Maximum size (nb of col/row) of a panel 59 K227_LOC=max(K227_LOC,2) 60 EFFECTIVE_SIZE = min(NBCOL_MAX-1, K227_LOC-1) 61cN - during bwd the effective size is useless 62 ELSE 63C complete buffer space can be used for a panel 64 EFFECTIVE_SIZE = min(NBCOL_MAX, K227_LOC) 65 ENDIF 66 IF (EFFECTIVE_SIZE.LE.0) THEN 67 write(6,*) 'Internal buffers too small to store ', 68 & ' ONE col/row of size', NNMAX 69 CALL MUMPS_ABORT() 70 ENDIF 71 DMUMPS_OOC_GET_PANEL_SIZE = EFFECTIVE_SIZE 72 RETURN 73 END FUNCTION DMUMPS_OOC_GET_PANEL_SIZE 74C 75 SUBROUTINE DMUMPS_PERMUTE_PANEL( IPIV, LPIV, ISHIFT, 76 & THE_PANEL, NBROW, NBCOL, KbeforePanel ) 77 IMPLICIT NONE 78C 79C Purpose: 80C ======= 81C 82C Permute rows of a panel, stored by columns, according 83C to permutation array IPIV. 84C IPIV is such that, for I = 1 to LPIV, row ISHIFT + I 85C in the front must be permuted with row IPIV( I ) 86C 87C Since the panel is not necessary at the beginning of 88C the front, let KbeforePanel be the number of pivots in the 89C front before the first pivot of the panel. 90C 91C In the panel, row ISHIFT+I-KbeforePanel is permuted with 92C row IPIV(I)-KbeforePanel 93C 94C Note: 95C ==== 96C 97C This routine can also be used to permute the columns of 98C a matrix (U) stored by rows. In that case, the argument 99C NBROW represents the number of columns, and NBCOL represents 100C the number of rows. 101C 102C 103C Arguments: 104C ========= 105C 106 INTEGER LPIV, ISHIFT, NBROW, NBCOL, KbeforePanel 107 INTEGER IPIV(LPIV) 108 DOUBLE PRECISION THE_PANEL(NBROW, NBCOL) 109C 110C Local variables: 111C =============== 112C 113 INTEGER I, IPERM 114C 115C Executable statements 116C ===================== 117C 118 DO I = 1, LPIV 119C Swap rows ISHIFT + I and PIV(I) 120 IPERM=IPIV(I) 121 IF ( I+ISHIFT.NE.IPERM) THEN 122 CALL dswap(NBCOL, 123 & THE_PANEL(I+ISHIFT-KbeforePanel,1), NBROW, 124 & THE_PANEL(IPERM-KbeforePanel,1), NBROW) 125 ENDIF 126 END DO 127 RETURN 128 END SUBROUTINE DMUMPS_PERMUTE_PANEL 129 SUBROUTINE DMUMPS_GET_OOC_PERM_PTR(TYPEF, 130 & NBPANELS, 131 & I_PIVPTR, I_PIV, IPOS, IW, LIW) 132 USE MUMPS_OOC_COMMON ! To access TYPEF_L and TYPEF_U 133 IMPLICIT NONE 134 INCLUDE 'mumps_headers.h' 135C 136C Purpose: 137C ======= 138C 139C Get the pointers in IW on pivoting information to be stored 140C during factorization and used during the solve phase. This 141C routine is both for the symmetric (TYPEF=TYPEF_L) and unsymmetric 142C cases (TYPEF=TYPEF_L or TYPEF_U). 143C The total size of this space is estimated during 144C fac_ass.F / fac_ass_ELT.F and must be: 145C * Symmetric case: 1 for NASS + 1 for NBPANELS_L + NBPANELS_L + NASS 146C * Unsymmetric case: 1 + (1+NBPANELS_L+NASS) + (1+NBPANELS_U+NASS) 147C Size computation is in routine DMUMPS_OOC_GET_PP_SIZES. 148C 149C At the end of the standard description of the structure of a node 150C (header, nb slaves, <slaves_list>, row indices, col indices), we 151C add, when panel version with pivoting is used: 152C 153C NASS (nb of fully summed variables) 154C NBPANELS_L 155C PIVRPTR(1:NBPANELS_L) 156C PIV_L (1:NASS) NASS (=IW(IPOS)(or NASS-PIVRPTR(1) in 157C the future, after compression) 158C NBPANELS_U 159C PIVRPTR(1:NBPANELS_U) 160C PIV_U (1:NASS) NASS (=IW(IPOS)(or NASS-PIVRPTR(1) in 161C the future, after compression) 162C 163C 164C Output parameters: 165C ================= 166C NBPANELS : nb of panels as estimated during assembly 167C I_PIVPTR : position in IW of the starting of the pointer list 168C (of size NBPANELS) of the pointers to the list of pivots 169C I_PIV : position in IW of the starting of the pivot permutation list 170C 171 INTEGER, intent(out) :: NBPANELS, I_PIVPTR, I_PIV 172 INTEGER, intent(in) :: TYPEF ! TYPEF_L or TYPEF_U 173 INTEGER, intent(in) :: LIW, IPOS 174 INTEGER IW(LIW) 175C Locals 176 INTEGER I_NBPANELS, I_NASS 177C 178 I_NASS = IPOS 179 I_NBPANELS = I_NASS + 1 ! L 180 NBPANELS = IW(I_NBPANELS) ! L 181 I_PIVPTR = I_NBPANELS + 1 ! L 182 I_PIV = I_PIVPTR + NBPANELS ! L 183C ... of size NASS = IW(I_NASS) 184 IF (TYPEF==TYPEF_U) THEN 185 I_NBPANELS = I_PIV+IW(I_NASS) ! U 186 NBPANELS = IW(I_NBPANELS) ! U 187 I_PIVPTR = I_NBPANELS + 1 ! U 188 I_PIV = I_PIVPTR + NBPANELS ! U 189 ENDIF 190 RETURN 191 END SUBROUTINE DMUMPS_GET_OOC_PERM_PTR 192 SUBROUTINE DMUMPS_OOC_PP_SET_PTR(K50,NBPANELS_L,NBPANELS_U, 193 & NASS, IPOS, IW, LIW ) 194 IMPLICIT NONE 195C 196C Purpose: 197C ======= 198C 199C Initialize the contents of PIV/PIVPTR/etc. that will store 200C pivoting information during the factorization. 201C NASS and NBPANELS are recorded. PIVPTR(1:NBPANELS) 202C is initialized to NASS+1. This will be modified during 203C the factorization in cases where permutations have to 204C be performed during the solve phase. 205C 206C Arguments: 207C ========= 208C 209 INTEGER K50 210 INTEGER IPOS, NASS, NBPANELS_L, NBPANELS_U, LIW 211 INTEGER IW(LIW) 212C 213C Local variables: 214C =============== 215C 216 INTEGER IPOS_U 217C Executable statements 218 IF (K50.EQ.1) THEN 219 WRITE(*,*) "Internal error: DMUMPS_OOC_PP_SET_PTR called" 220 ENDIF 221 IW(IPOS)=NASS 222 IW(IPOS+1)=NBPANELS_L 223 IW(IPOS+2:IPOS+1+NBPANELS_L)=NASS+1 224 IF (K50 == 0) THEN 225 IPOS_U=IPOS+2+NASS+NBPANELS_L 226 IW(IPOS_U)=NBPANELS_U 227 IW(IPOS_U+1:IPOS_U+NBPANELS_U)=NASS+1 228 ENDIF 229 RETURN 230 END SUBROUTINE DMUMPS_OOC_PP_SET_PTR 231 SUBROUTINE DMUMPS_OOC_PP_TRYRELEASE_SPACE ( 232 & IWPOS, IOLDPS, IW, LIW, MonBloc, NFRONT, KEEP 233 & ) 234 USE DMUMPS_OOC 235 IMPLICIT NONE 236 INCLUDE 'mumps_headers.h' 237C 238C Purpose: 239C ======= 240C If space used was at the top of the stack then 241C try to free space by detecting that 242C no permutation needs to be applied during 243C solve on panels. 244C One position is left (I_NASS) and set to -1 245C to indicate that permutation not needed at solve. 246C 247C Arguments: 248C ========= 249C 250 INTEGER, INTENT(IN) :: IOLDPS, LIW, NFRONT, 251 & KEEP(500) 252 INTEGER, INTENT(INOUT) :: IWPOS, IW(LIW) 253 TYPE(IO_BLOCK), INTENT(IN):: MonBloc 254C 255C Local variables: 256C =============== 257C 258 INTEGER :: NBPANELS_L,I_PIVRPTR_L, I_PIVR_L, NBPANELS_U, 259 & I_PIVRPTR_U, I_PIVR_U, XSIZE, IBEGOOC 260 LOGICAL FREESPACE ! set to true when permutation not needed 261C Executable statements 262 IF (KEEP(50).EQ.1) RETURN ! no pivoting 263C -------------------------------- 264C quick return if record is not at 265C the top of stack of L factors 266 IF ((IOLDPS+IW(IOLDPS+XXI)).NE.IWPOS) RETURN 267C --------------------------------------------- 268C Panel+pivoting: get pointers on each subarray 269C --------------------------------------------- 270 XSIZE = KEEP(IXSZ) 271 IBEGOOC = IOLDPS+2*NFRONT+6+IW(IOLDPS+5+XSIZE)+XSIZE 272C -- get L related data 273 CALL DMUMPS_GET_OOC_PERM_PTR(TYPEF_L, NBPANELS_L, 274 & I_PIVRPTR_L, I_PIVR_L, 275 & IBEGOOC, IW, LIW) 276 FREESPACE = 277 & (MonBloc%LastPiv.EQ.(IW(I_PIVRPTR_L)-1)) 278 IF (KEEP(50).EQ.0) THEN 279C -- get U related dataA 280 CALL DMUMPS_GET_OOC_PERM_PTR(TYPEF_U, NBPANELS_U, 281 & I_PIVRPTR_U, I_PIVR_U, 282 & IBEGOOC, IW, LIW) 283 FREESPACE = FREESPACE .AND. 284 & (MonBloc%LastPiv.EQ.(IW(I_PIVRPTR_U)-1)) 285 ENDIF 286C --------------------------------- 287C Check if permutations eed be 288C performed on panels during solve 289C -------------------------------- 290 IF (FREESPACE) THEN 291C -- compress memory for that node: keep one entry set to -7777 292 IW(IBEGOOC) = -7777 ! will be tested during solve 293 IW(IOLDPS+XXI) = IBEGOOC 294 & - IOLDPS + 1 ! new size of inode's record 295 IWPOS = IBEGOOC+1 ! move back to top of stack 296 ENDIF 297 RETURN 298 END SUBROUTINE DMUMPS_OOC_PP_TRYRELEASE_SPACE 299C 300 SUBROUTINE DMUMPS_OOC_GET_PP_SIZES(K50, NBROW_L, NBCOL_U, NASS, 301 & NBPANELS_L, NBPANELS_U, LREQ) 302 USE DMUMPS_OOC ! To call DMUMPS_OOC_PANEL_SIZE 303 IMPLICIT NONE 304C 305C Purpose 306C ======= 307C 308C Compute the size of the workspace required to store the permutation 309C information during factorization, so that solve can permute back 310C what has to be permuted (this could not be done during factorization 311C because it was already on disk). 312C 313C Arguments 314C ========= 315C 316 INTEGER, intent(IN) :: K50, NBROW_L, NBCOL_U, NASS 317 INTEGER, intent(OUT) :: NBPANELS_L, NBPANELS_U, LREQ 318 NBPANELS_L=-99999 319 NBPANELS_U=-99999 320C 321C Quick return in SPD case (no pivoting) 322C 323 IF (K50.EQ.1) THEN 324 LREQ = 0 325 RETURN 326 ENDIF 327C 328C L information is always computed 329C 330 NBPANELS_L = (NASS / DMUMPS_OOC_PANEL_SIZE(NBROW_L))+1 331 LREQ = 1 ! Store NASS 332 & + 1 ! Store NBPANELS_L 333 & + NASS ! Store permutations 334 & + NBPANELS_L ! Store pointers on permutations 335 IF (K50.eq.0) THEN 336C 337C Also take U information into account 338C 339 NBPANELS_U = (NASS / DMUMPS_OOC_PANEL_SIZE(NBCOL_U) ) +1 340 LREQ = LREQ + 1 ! Store NBPANELS_U 341 & + NASS ! Store permutations 342 & + NBPANELS_U ! Store pointers on permutations 343 ENDIF 344 RETURN 345 END SUBROUTINE DMUMPS_OOC_GET_PP_SIZES 346 SUBROUTINE DMUMPS_OOC_PP_CHECK_PERM_FREED 347 & (IW_LOCATION, MUST_BE_PERMUTED) 348 IMPLICIT NONE 349 INTEGER, INTENT(IN) :: IW_LOCATION 350 LOGICAL, INTENT(INOUT) :: MUST_BE_PERMUTED 351C 352C Purpose 353C ======= 354C 355C Reset MUST_BE_PERMUTED to .FALSE. when we detect 356C that the DMUMPS_OOC_PP_TRY_RELEASE_SPACE has freed 357C the permutation information (see that routine). 358C 359 IF (IW_LOCATION .EQ. -7777) THEN 360 MUST_BE_PERMUTED = .FALSE. 361 ENDIF 362 RETURN 363 END SUBROUTINE DMUMPS_OOC_PP_CHECK_PERM_FREED 364