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