pragmg
C PRAGMG SOURCE GOUNAND 25/03/24 21:15:08 12216 $ LNMV,INCX,ITER,INMV, $ RESID,KPREC, $ NREST,ICALRS,IDDOT,IMVEC,KTIME,LTIME,IMPR,IRET) IMPLICIT REAL*8 (A-H,O-Z) IMPLICIT INTEGER (I-N) C*********************************************************************** C NOM : PRAGMG C DESCRIPTION : C Préparation de la résolution d'un système linéaire Ax=b C par une méthode Multigrille Algébrique C C LANGAGE : ESOPE C AUTEUR : Stéphane GOUNAND (CEA/DRN/DMT/SEMT/TTMF) C mél : gounand@semt2.smts.cea.fr C REFERENCE (bibtex-like) : C*********************************************************************** C*********************************************************************** C VERSION : v1, 17/06/08, version initiale C HISTORIQUE : 17/06/08 : Crétation 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*********************************************************************** * * .. Includes et pointeurs associés .. * -INC PPARAM -INC CCOPTIO -INC CCREEL -INC SMLREEL INTEGER JG POINTEUR LRES.MLREEL -INC SMLENTI POINTEUR LNMV.MLENTI POINTEUR KTYP.MLENTI POINTEUR KNOD.MLENTI POINTEUR IBLOCK.MLENTI POINTEUR IPERM.MLENTI POINTEUR JPERM.MLENTI -INC SMMATRIK POINTEUR MAPREC.MATRIK POINTEUR KMORS.PMORS POINTEUR KISA.IZA POINTEUR AMORS.PMORS POINTEUR AISA.IZA POINTEUR KS2B.IZA,RES.IZA POINTEUR INCX.IZA,INCDX.IZA POINTEUR INVDIA.IZA POINTEUR ILUM.PMORS POINTEUR ILUI.IZA -INC SMTABLE POINTEUR KTIME.MTABLE CHARACTER*8 CHARI LOGICAL LTIME,LOGII,LBLOCK * .. Parameters * This is a breakdown tolerance for BiCGSTAB-type method REAL*8 BRTOL *STAT-INC SMSTAT * .. Scalar Arguments .. INTEGER ITER, KPREC, IMPR, IRET INTEGER ICNT REAL*8 RESID,TOL,BNRM2,RNRM2,XFACT * .. * Vars reqd for STOPTEST2 * REAL*8 TOL, BNRM2 * .. * .. External subroutines .. * EXTERNAL STOPTEST2 INTEGER NBVA,NJA,NTT,NTTPRE EXTERNAL GNRM2 * .. * .. Executable Statements .. * * WRITE(IOIMP,*) 'Debut de pragmg' IRET = 0 IVALI=0 XVALI=0.D0 LOGII=.FALSE. IRETI=0 IAT =0 XVALR=0.D0 IRETR=0 IST =0 * * On récupère les paramètres * * SEGACT MATRIK SEGACT KMORS SEGACT KISA NBVA=KISA.A(/1) SEGACT KS2B SEGINI,RES=KS2B SEGACT INCX*MOD nbva=INCX.A(/1) SEGINI INCDX C C Initialisation de l'historique de convergence C JG=ITER+1 SEGINI LNMV SEGINI LRES * * Autres paramètres * IJOB=0 IF (IMPR.GT.2) THEN IPRINT=IOIMP ELSE IPRINT=-1 ENDIF TOL=RESID ICNT=0 * * AGMG ne fait que du résidu relatif d'où les petits ajustements * suivants. * * res = b - AX IF (ICALRS.EQ.1) BNRM2=RNRM2 IF (BNRM2.LT.XPETIT) BNRM2=1.D0 RESID=RNRM2 / BNRM2 LNMV.LECT(ICNT+1)=1 * IF (RESID.LE.TOL) THEN ITER=0 GOTO 30 ENDIF * IF (ICALRS.EQ.0) THEN XFACT=1.D0/RESID TOL=TOL*XFACT ENDIF * * To use the standard AGMG library, you should make sure that it * is compiled with same compiler and options than Castem's and that * the sequential example furnished with AGMG works. * Then it is sufficient to put agmg_seq.o and agmg.o in the * current directory and use essai for linking. * * No interface to the parallel version of agmg for now * WRITE(IOIMP,*) '***********************************' WRITE(IOIMP,*) ' ' WRITE(IOIMP,*) 'Please uncomment the CALL AGMG(...', $ ' in the pragmg.eso subroutine if you wish to use' WRITE(IOIMP,*) 'the AGMG library by Y. Notay' WRITE(IOIMP,*) ' ' WRITE(IOIMP,*) '***********************************' * 251 2 *Tentative d'utilisation d'une option non implémentée IRET=-1 GOTO 9999 ********************************************************************* * * AGMG v3.3.7_block call (standard sequential version) * * 1) Trouver le nombre de blocs c$$$ NBLOCK=0 c$$$ segact ktyp c$$$ ntt=ktyp.lect(/1) c$$$ if (nrest.lt.0) then c$$$ segact knod c$$$ ntt2=knod.lect(/1) c$$$ if (ntt2.ne.ntt) THEN c$$$ call erreur(5) c$$$ goto 9999 c$$$ endif c$$$ endif c$$$ jg=ntt c$$$ segini iperm c$$$ segini jperm c$$$ nja=kisa.a(/1) c$$$ DO i=1,ntt c$$$ jblock=ktyp.lect(i) c$$$ if (jblock.gt.nblock) nblock=jblock c$$$ enddo c$$$ if (impr.gt.2) then c$$$ write(ioimp,*) 'Nb d''inconnues=',ntt c$$$ write(ioimp,*) 'Nb de termes=',kmors.ja(/1) c$$$ write(ioimp,*) 'Nb de termes 2=',nja c$$$ write(ioimp,*) 'Nb de blocs detectes nblock=',nblock c$$$ endif c$$$ JG=NBLOCK+1 c$$$ SEGINI IBLOCK c$$$ lblock=nblock.gt.1 c$$$ 187 FORMAT (5X,10I8) c$$$ if (lblock) then c$$$* c$$$* 2) Trouver le nombre d'inconnus par blocs c$$$ DO i=1,ktyp.lect(/1) c$$$ jblock=ktyp.lect(i) c$$$ iblock.lect(jblock)=iblock.lect(jblock)+1 c$$$ enddo c$$$ if (impr.gt.2) then c$$$ write(ioimp,*) 'Nb inconnues par blocs' c$$$ write(ioimp,187) (iblock.lect(I),I=1,iblock.lect(/1)) c$$$ endif c$$$* 3) D'où le segment de repérage c$$$ do i=nblock,1,-1 c$$$ iblock.lect(i+1)=iblock.lect(i) c$$$ enddo c$$$ if (impr.gt.2) then c$$$ write(ioimp,*) 'Segment de repérage tmp' c$$$ write(ioimp,187) (iblock.lect(I),I=1,iblock.lect(/1)) c$$$ endif c$$$ iblock.lect(1)=1 c$$$ do i=1,nblock c$$$ iblock.lect(i+1)=iblock.lect(i+1)+iblock.lect(i) c$$$ enddo c$$$ if (impr.gt.2) then c$$$ write(ioimp,*) 'Segment de repérage' c$$$ write(ioimp,187) (iblock.lect(I),I=1,iblock.lect(/1)) c$$$ endif c$$$* 4) Construction des permutations c$$$ ntt=kmors.ia(/1)-1 c$$$ if (impr.gt.2) then c$$$ write(ioimp,*) 'Nb d''inconnues 2 ntt=',ntt c$$$ endif c$$$ ktt=1 c$$$ do kblock=1,nblock c$$$ do itt=1,ntt c$$$ jblock=ktyp.lect(itt) c$$$ if (kblock.eq.jblock) then c$$$ iperm.lect(itt)=ktt c$$$ jperm.lect(ktt)=itt c$$$ ktt=ktt+1 c$$$ endif c$$$ enddo c$$$ enddo c$$$* write(ioimp,*) 'Permutation i' c$$$* write(ioimp,187) (iperm.lect(I),I=1,iperm.lect(/1)) c$$$* write(ioimp,*) 'Permutation j' c$$$* write(ioimp,187) (jperm.lect(I),I=1,jperm.lect(/1)) c$$$* c$$$* 5) Permutation de la matrice et du second membre c$$$* c$$$ SEGINI,AMORS=KMORS c$$$ SEGINI,AISA=KISA c$$$* SEGINI,AMORS c$$$* SEGINI,AISA c$$$* write(ioimp,*) 'Avant permutation' c$$$* CALL ECMORS(AMORS,AISA,3) c$$$ job=1 c$$$ CALL DPERM(ntt,kisa.a,kmors.ja,kmors.ia, c$$$ $ aisa.a,amors.ja,amors.ia,iperm.lect,jperm.lect,job) c$$$ CALL DVPERM(ntt,res.a,iperm.lect) c$$$ if (nrest.lt.0) CALL IVPERM(ntt,knod.lect,iperm.lect) c$$$* write(ioimp,*) 'Apres permutation' c$$$* CALL ECMORS(AMORS,AISA,3) c$$$ else c$$$ iblock.lect(1)=1 c$$$ iblock.lect(2)=ntt+1 c$$$ if (impr.gt.2) then c$$$ write(ioimp,*) 'Segment de repérage' c$$$ write(ioimp,187) (iblock.lect(I),I=1,iblock.lect(/1)) c$$$ endif c$$$* Pas de permutation c$$$ SEGINI,AMORS=KMORS c$$$ SEGINI,AISA=KISA c$$$ endif c$$$* c$$$* Changement automatique du signe des lignes de la matrice c$$$* et du second membre si le terme diagonal est négatif. c$$$* c$$$* SEGACT,AMORS*mod c$$$* segact,AISA*mod c$$$ DO I=1,NTT c$$$ IFOUND=0 c$$$ DO J=AMORS.IA(I),(AMORS.IA(I+1)-1) c$$$* WRITE(IOIMP,*) 'I,J=',I,J c$$$* WRITE(IOIMP,*) 'JA(J)=',AMORS.JA(J) c$$$ IF (AMORS.JA(J).EQ.I) THEN c$$$* WRITE(IOIMP,*) 'AISA.A(J)=',AISA.A(J) c$$$ IF (AISA.A(J).GT.XZERO) THEN c$$$ IFOUND=1 c$$$ ELSEIF (AISA.A(J).LT.XZERO) THEN c$$$ IFOUND=-1 c$$$ ENDIF c$$$ GOTO 10 c$$$ ENDIF c$$$ ENDDO c$$$ 10 CONTINUE c$$$* WRITE(IOIMP,*) 'IFOUND=',IFOUND c$$$ IF (IFOUND.EQ.0) THEN c$$$ WRITE(IOIMP,*) 'The ',I c$$$ $ ,'th diagonal term of the matrix is nil' c$$$ IRET=-3 c$$$ GOTO 9999 c$$$ ELSEIF (IFOUND.EQ.-1) THEN c$$$ RES.A(I)=-1.D0*RES.A(I) c$$$ DO J=AMORS.IA(I),(AMORS.IA(I+1)-1) c$$$ AISA.A(J)=-1.D0*AISA.A(J) c$$$ ENDDO c$$$ ENDIF c$$$ ENDDO c$$$* WRITE(IOIMP,*) '4' c$$$* CALL ECMORS(AMORS,AISA,3) c$$$ c$$$ c$$$ ITR2=ITER-1 c$$$ instance=0 c$$$ IF (NREST.GE.0) then c$$$* IPRINT=-978 c$$$ CALL DAGMG(NTT,AISA.A,AMORS.JA,AMORS.IA,RES.A,INCDX.A, c$$$ $ IJOB,IPRINT,NREST,ITR2,TOL,NBLOCK,IBLOCK.LECT) c$$$ ELSE c$$$ IF (.NOT.lblock) THEN c$$$ write(ioimp,*) 'The AGMG Stokes solver needs blocks' c$$$ moterr(1:8)='pragmg' c$$$ call erreur(1127) c$$$ return c$$$ ENDIF c$$$ NRESTA=ABS(NREST) c$$$ if (nresta.GT.1) then c$$$ nddl1=iblock.lect(2)-iblock.lect(1) c$$$ do i=2,nblock c$$$ nddl=iblock.lect(i+1)-iblock.lect(i) c$$$ if (nddl.ne.nddl1) then c$$$ write(ioimp,*) 'Le bloc ',i,' de taille =',nddl c$$$ write(ioimp,*) 'na pas la meme taille que le bloc 1 =' c$$$ $ ,nddl1 c$$$ moterr(1:8)='pragmg' c$$$ call erreur(1127) c$$$ return c$$$ endif c$$$ enddo c$$$* c$$$* Vérif que les inconnues sont dans le même ordre à l'intérieur de c$$$* chaque bloc c$$$* c$$$ do i=2,nblock c$$$ nddl=iblock.lect(i+1)-iblock.lect(i) c$$$ ideb=iblock.lect(i) c$$$ do iddl=1,nddl c$$$ inod1=knod.lect(iddl) c$$$ inodi=knod.lect(ideb+iddl-1) c$$$ if (inodi.ne.inod1) then c$$$ write(ioimp,*) 'Dans le bloc ',i,' le ddl ',iddl c$$$ $ ,' porte sur le noeud inodi=',inodi c$$$ write(ioimp,*) 'Dans le bloc ',1,' le ddl ',iddl c$$$ $ ,' porte sur le noeud inod1=',inod1 c$$$ write(ioimp,*) 'inod1 != inodi est une erreur !' c$$$ moterr(1:8)='pragmg' c$$$ call erreur(1127) c$$$ return c$$$ endif c$$$ enddo c$$$ enddo c$$$ c$$$ call DAGMG_STOKES_INTPARAM('smoothtype',-51,instance) c$$$ call DAGMG_STOKES_INTPARAM('pointcoarsening',1,instance) c$$$ call DAGMG_STOKES_INTPARAM('Ltransform',1,instance) c$$$ endif c$$$ CALL DAGMG_STOKES(NTT,AISA.A,AMORS.JA,AMORS.IA,RES.A,INCDX.A, c$$$ $ IJOB,IPRINT,NREST,ITR2,TOL,NBLOCK,IBLOCK.LECT) c$$$ c$$$ ENDIF c$$$ CALL dagmg_status(istat,instance) c$$$ CALL dagmg_niter(itr2,instance) c$$$ c$$$ if (lblock) then c$$$ CALL DVPERM(ntt,incdx.a,jperm.lect) c$$$ endif c$$$ SEGSUP IBLOCK c$$$ segsup iperm c$$$ segsup jperm c$$$ c$$$ c$$$ c$$$* X = X_0 + \delta X c$$$ CALL GAXPY(1.D0,INCDX,INCX) c$$$* Résidu final c$$$ CALL GCOPY(KS2B,RES) c$$$ CALL GMOMV(IMVEC,'N',-1.D0,KMORS,KISA,INCX,1.D0,RES) c$$$ RNRM2=GNRM2(RES) c$$$ RESID=RNRM2/BNRM2 c$$$* c$$$ IF (istat.NE.0) THEN c$$$ IRET=1 c$$$ ELSE c$$$ IRET=0 c$$$ ENDIF c$$$ ITER=ITR2 c$$$* c$$$ ICNT=ICNT+1 c$$$ LRES.PROG(ICNT+1)=RESID c$$$ LNMV.LECT(ICNT+1)=1+ITER c$$$ INMV=1+ITER * * End of AGMG call (standard sequential version) * ********************************************************************* * IF (LTIME) THEN CHARI='MGAGGREG' $ 'ENTIER ',IAT,XVALR,CHARR,LOGIR,IRETR) CHARI='MGSOLUTI' $ 'ENTIER ',IST,XVALR,CHARR,LOGIR,IRETR) ENDIF * C C Désactivation C 30 CONTINUE JG=ICNT+1 SEGADJ LRES SEGDES LRES SEGADJ LNMV SEGDES LNMV SEGSUP INCDX SEGDES INCX SEGDES KS2B SEGSUP RES SEGSUP AISA * SEGSUP ATYP SEGSUP AMORS SEGDES KISA SEGDES KTYP if (nrest.lt.0) SEGDES KNOD SEGDES KMORS SEGDES MATRIK C C A breakdown has occured in the CGS method C IF (IRET.LT.0) GOTO 9999 * * Normal termination * RETURN * * Format handling * * 1002 FORMAT(10(1X,1PE11.4)) * * Error handling * 9999 CONTINUE WRITE(IOIMP,*) 'An error was detected in pragmg.eso' RETURN * * End of PRAGMG * END
© Cast3M 2003 - Tous droits réservés.
Mentions légales