meilut
C MEILUT SOURCE GOUNAND 05/06/06 21:15:39 5078 $ XLFIL,XDTOL,NNZMLU, $ ALU,JLU,JU,NNZLU, $ IWORK,JWORK,RWORK, $ IVARI,IMPR,IRET) IMPLICIT REAL*8 (A-H,O-Z) IMPLICIT INTEGER (I-N) C*********************************************************************** C NOM : MEILUT C DESCRIPTION : C Calcul du préconditionneur ILUT d'une matrice Morse (IVARI=0) C ou d'une variante qui remplit mieux la mémoire et fonctionne mieux C quelquefois (IVARI=1). C ILUT : Incomplete LU factorization with dual truncation strategy C La matrice Morse est au format CSR (Column Sparse Row) C Le préconditionneur est au format MSR (Modified Sparse Row, C stockage de l'inverse de la diagonale) (ALU, JLU). C JU est un tableau supplémentaire pour le repérage des diagonales. C (voir la doc. de Sparskit version 2) C C LANGAGE : FORTRAN 77 (sauf E/S) C AUTEUR : Stéphane GOUNAND (CEA/DRN/DMT/SEMT/LTMF) C mél : gounand@semt2.smts.cea.fr C REFERENCE (bibtex-like) : C @BOOK{templates, C AUTHOR={R.Barrett, M.Berry, T.F.Chan, J.Demmel, J.Donato, C J.Dongarra, V.Eijkhout, R.Pozo, C.Romine, C H. Van der Vorst}, C TITLE={Templates for the Solution of Linear Systems : C Building Blocks for Iterative Methods}, C PUBLISHER={SIAM}, YEAR={1994}, ADDRESS={Philadelphia,PA} } C -> URL : http://www.netlib.org/templates/Templates.html C Sparskit : a basic tool kit for sparse matrix computations C Version 2 (Youcef Saad) C -> URL : http://www.cs.umn.edu/Research/arpa/SPARSKIT/sparskit.html C REMARQUES : C Quelques parties pourraient être améliorés : C - l'algorithme de quicksplit (cf.qsplit.eso) C - la partie où l'on doit effectuer l'élimination dans le bon ordre C pourrait utiliser un algorithme de tri type quicksort C C*********************************************************************** C APPELES : QSPLIT C APPELE PAR : PRILUT C*********************************************************************** C ENTREES : NTT,NNZA,A,JA,IA,XLFIL,XDTOL,NNZMLU,IVARI C ENTREES/SORTIES : IWORK,JWORK,RWORK (tableaux de travail) C SORTIES : ALU,JLU,JU,NNZLU C CODE RETOUR (IRET) : = 0 si tout s'est bien passé C*********************************************************************** C VERSION : v1, 20/03/00, réécriture totale C VERSION : v1, 23/02/00, version initiale C HISTORIQUE : v1, 23/02/00, création C HISTORIQUE : C HISTORIQUE : C*********************************************************************** C Prière de PRENDRE LE TEMPS de compléter les commentaires C en cas de modification de ce sous-programme afin de faciliter C la maintenance ! C*********************************************************************** -INC PPARAM -INC CCOPTIO -INC CCREEL * .. Scalar Arguments .. INTEGER NTT,NNZA,NNZMLU,NNZLU INTEGER IVARI,IMPR,IRET REAL*8 XDTOL,XLFIL * .. * .. Array Arguments .. REAL*8 A(NNZA),ALU(NNZMLU+1) INTEGER JA(NNZA),IA(NTT+1),JU(NTT),JLU(NNZMLU+1) INTEGER IWORK(NTT) INTEGER JWORK(NTT) REAL*8 RWORK(NTT) * * .. Variables locales * .. Parameters * .. C Nombre de pivots petits INTEGER NBPIVP C Nombre de pivots inférieurs à 0 INTEGER NBPIVI * INTEGER ILFIL,ILFILL,ILFILU INTEGER COL,COLLU INTEGER IJA,ILEN,ILENL,ILENU,ITT,ISTRT,ISTOP INTEGER JJL,JPOS,JROW,KJL,KLU INTEGER LEN,LENL,LENU INTEGER JU0,ITMP REAL*8 XNTLIG * REAL*8 XPOND1,XPOND2 * * Executable statements * IF (XLFIL.LT.0.D0) THEN WRITE(IOIMP,*) 'XLFIL.LT.0.D0 non acceptable' GOTO 9999 ENDIF NBPIVP=0 NBPIVI=0 c----------------------------------------------------------------------- c initialize ju0 (points to next element to be added to alu,jlu) c and pointer array. c----------------------------------------------------------------------- JU0=NTT+2 JLU(1)=JU0 * * On boucle sur les ddl * DO 1 ITT=1,NTT * Calcul de la norme de la ittème ligne ISTRT=IA(ITT) ISTOP=IA(ITT+1)-1 TNORM=ZERO DO 11 IJA=ISTRT,ISTOP TNORM=TNORM+ABS(A(IJA)) 11 CONTINUE TNORM=TNORM/DBLE(ISTOP-ISTRT+1) IF (TNORM.LE.XPETIT) THEN WRITE(IOIMP,*) 'La ligne ',ITT,' est nulle...' GOTO 9999 ENDIF * On stocke la ittème ligne de A dans IWORK,RWORK en distinguant les * parties triangulaires inférieures et supérieurs. * * On peut le programmer autrement compte tenu du fait que les * colonnes sont ordonnées * LENL=0 LENU=0 DO 12 IJA=ISTRT,ISTOP COL=JA(IJA) VAL=A(IJA) IF (COL.LT.ITT) THEN LENL=LENL+1 IWORK(LENL)=COL RWORK(LENL)=VAL JWORK(COL) =LENL ELSEIF (COL.EQ.ITT) THEN IWORK(ITT)=ITT RWORK(ITT)=VAL JWORK(ITT)=ITT ELSE LENU=LENU+1 IWORK(ITT+LENU)=COL RWORK(ITT+LENU)=VAL JWORK(COL) =ITT+LENU ENDIF 12 CONTINUE IF (IVARI.EQ.1) THEN * Stratégie : on remplit autant que possible * normale meilug XNTLIG=DBLE(NNZMLU-JU0+1)/DBLE(NTT-ITT+1) * on retire la diagonale * ILFIL=INT(XNTLIG/2.D0) ILFIL=INT((XNTLIG-1.D0)/2.D0) * Stratégie meilug pondérée globalement * XNTLIG=(DBLE(NNZMLU-JU0+1)/DBLE(NTT-ITT+1)) * $ *(1.5D0-0.5D0*(DBLE(ITT-1)/DBLE(NTT-1))) * ILFIL=INT(XNTLIG/2.D0) * Stratégie normale (idem meilut) ELSEIF (IVARI.EQ.0) THEN XNTLIG=DBLE(NNZA)/DBLE(NTT) * Pour faire comme dans meiltp * ILFIL=INT(XNTLIG*XLFIL/2.D0) ILFIL=INT((XNTLIG-1.D0)*XLFIL/2.D0) ELSE WRITE(IOIMP,*) 'Erreur de programmation IVARI=',IVARI ENDIF * On a enlevé les : * Corrections pour les extrémités de la matrice * IF (ILFIL.GT.ITT-1) THEN * ILFILL=ITT-1 * ILFILU=(2*ILFIL)-ILFILL * ELSEIF (ILFIL.GT.(NTT-ITT)) THEN * ILFILU=NTT-ITT * ILFILL=(2*ILFIL)-ILFILU * ELSE * ILFILL=ILFIL * ILFILU=ILFIL * ENDIF * WRITE(IOIMP,*) 'itt,ilfil,ilfill,ilfilu=',ITT,ILFIL,ILFILL * $ ,ILFILU * Stratégie normale ILFILL=ILFIL ILFILU=ILFIL * Stratégie pondérée localement * XPOND1=DBLE(LENL)/DBLE(LENL+LENU) * XPOND2=DBLE(LENU)/DBLE(LENL+LENU) * ILFILL=INT(XPOND1*DBLE(ILFIL*2)) * ILFILU=(ILFIL*2)-ILFILL * Elimination avec les lignes précédentes JJL=0 LEN=0 13 CONTINUE JJL=JJL+1 IF (JJL.LE.LENL) THEN c----------------------------------------------------------------------- c in order to do the elimination in the correct order we must select c the smallest column index among jw(k), k=jj+1, ..., lenl. c----------------------------------------------------------------------- JROW=IWORK(JJL) KJL=JJL c determine smallest column index DO 132 ILENL=JJL+1,LENL IF (IWORK(ILENL).LT.JROW) THEN JROW=IWORK(ILENL) KJL=ILENL ENDIF 132 CONTINUE IF (KJL.NE.JJL) THEN ITMP=IWORK(JJL) IWORK(JJL)=IWORK(KJL) IWORK(KJL)=ITMP JWORK(JROW)=JJL JWORK(ITMP)=KJL RTMP=RWORK(JJL) RWORK(JJL)=RWORK(KJL) RWORK(KJL)=RTMP ENDIF c zero out element in row by setting jw(n+jrow) to zero. JWORK(JROW)=0 c get the multiplier for row to be eliminated (jrow). FACT=RWORK(JJL)*ALU(JROW) IF (ABS(FACT).LE.XDTOL) THEN GOTO 13 ENDIF c c combine current row and row jrow c DO 134 KLU=JU(JROW),JLU(JROW+1)-1 TERMLU=FACT*ALU(KLU) COLLU =JLU(KLU) JPOS =JWORK(COLLU) IF (COLLU.GE.ITT) THEN c dealing with upper part (including diagonal) IF (JPOS.EQ.0) THEN c this is a fill-in element LENU=LENU+1 IF (LENU.GT.NTT-ITT) THEN WRITE(IOIMP,*) 'pb. matrice U' GOTO 9999 ENDIF IWORK(ITT+LENU)=COLLU JWORK(COLLU)=ITT+LENU RWORK(ITT+LENU)=-TERMLU ELSE c this is not a fill-in element RWORK(JPOS)=RWORK(JPOS)-TERMLU ENDIF ELSE c dealing with lower part. IF (JPOS.EQ.0) THEN c this is a fill-in element LENL=LENL+1 IF (LENL.GT.ITT-1) THEN WRITE(IOIMP,*) 'pb. matrice L' GOTO 9999 ENDIF IWORK(LENL) =COLLU JWORK(COLLU)=LENL RWORK(LENL) =-TERMLU ELSE c this is not a fill-in element RWORK(JPOS)=RWORK(JPOS)-TERMLU ENDIF ENDIF 134 CONTINUE c store this pivot element -- (from left to right -- no danger of c overlap with the working elements in L (pivots). LEN=LEN+1 IWORK(LEN)=JROW RWORK(LEN)=FACT GOTO 13 ENDIF c reset double-pointer to zero (U-part including diagonal) DO 14 ILENU=0,LENU JWORK(IWORK(ITT+ILENU))=0 14 CONTINUE c update L-matrix LENL=LEN LEN=MIN(LENL,ILFILL) c sort by quick-split $ IMPR,IRET) c store L-part DO 15 ILEN=1,LEN JLU(JU0)=IWORK(ILEN) ALU(JU0)=RWORK(ILEN) JU0=JU0+1 15 CONTINUE c save pointer to beginning of row ii of U JU(ITT)=JU0 c update U-matrix -- first apply dropping strategy LEN=0 DO 16 ILEN=1,LENU IF (ABS(RWORK(ITT+ILEN)).GT.XDTOL*TNORM) THEN LEN=LEN+1 IWORK(ITT+LEN)=IWORK(ITT+ILEN) RWORK(ITT+LEN)=RWORK(ITT+ILEN) ENDIF 16 CONTINUE LENU=LEN LEN=MIN(LENU,ILFILU) c sort by quick-split $ IMPR,IRET) c copy DO 17 ILEN=ITT+1,ITT+LEN JLU(JU0)=IWORK(ILEN) ALU(JU0)=RWORK(ILEN) JU0=JU0+1 17 CONTINUE c store inverse of diagonal element of u VALPIV=RWORK(ITT) WRITE(IOIMP,*) 'Pivot',ITT,'nul : ', $ 'le préconditionnement ILUT est impossible.' IRET=-2 GOTO 9999 ELSE NBPIVP=NBPIVP+1 ENDIF NBPIVI=NBPIVI+1 ENDIF ENDIF ALU(ITT)=ONE/RWORK(ITT) c update pointer to beginning of next row of U. JLU(ITT+1)=JU0 1 CONTINUE NNZLU=JLU(NTT+1)-1 * * Warning(s) * IF (IMPR.GT.0) THEN IF (NBPIVP.GT.0) THEN WRITE(IOIMP,*) 'WARNING !', ENDIF *! IF (NBPIVI.GT.0) THEN *! WRITE(IOIMP,*) 'WARNING !', *! $ ' meilut :',NBPIVI,' pivot(s) < 0' *! ENDIF ENDIF * * Normal termination * IRET=0 RETURN * * Error handling * 9999 CONTINUE IRET=1 WRITE(IOIMP,*) 'An error was detected in meilut.eso' RETURN * * End of MEILUT * END
© Cast3M 2003 - Tous droits réservés.
Mentions légales