calnu4
C CALNU4 SOURCE PV 20/09/26 21:15:24 10724
$ IRENU,
$ NEWNUM,
$ IMPR,IRET)
IMPLICIT REAL*8 (A-H,O-Z)
IMPLICIT INTEGER (I-N)
C***********************************************************************
C NOM : CALNU4
C PROJET : Noyau linéaire NLIN
C DESCRIPTION : Calcul d'une renumérotation avec minimisation d'un
C profil PUIS placement des inconnues suivant l'ordre
C donné par LIORD
C Dans calnum, on effectuait les choses suivantes :
C - minimisation du profil sur les ddl sans les ML.
C - insertion des ML dans la nouvelle numérotation
C Maintenant, on essaie la chose suivante :
C - minimisation du profil sur les ddl AVEC les ML.;
C - retrait des ML de la numérotation ;
C - réinsertion des ML pour les placer après les ddl non
C ML auxquels ils sont liés.
C
C IRENU=1 'RIEN' : pas de renumérotation
C 2 'SLOA' : algorithme de chez Sloan
C 3 'GIPR' : Gibbs-King (profile reduction)
C 4 'GIBA' : Gibbs-Poole-Stockmeyer (bandwidth reduction)
C
C LANGAGE : ESOPE
C AUTEUR : Stéphane GOUNAND (CEA/DRN/DMT/SEMT/LTMF)
C mél : gounand@semt2.smts.cea.fr
C***********************************************************************
C APPELES : RENUME
C APPELES (UTIL.) : ISETI, ISHELI, RSETXI
C APPELE PAR : PRASEM
C***********************************************************************
C ENTREES : KMINCT, PMTOT, IRENU
C SORTIES : NEWNUM
C CODE RETOUR (IRET) : = 0 si tout s'est bien passé
C***********************************************************************
C VERSION : v1, 01/04/04, version initiale
C HISTORIQUE : v1, 01/04/04, création
C HISTORIQUE : voir note * SG 10/06/2015
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 SMMATRIK
POINTEUR KMINCT.MINC
POINTEUR PMTOT.PMORS
-INC SMLENTI
INTEGER JG
POINTEUR LITYP.MLENTI
POINTEUR LINIV.MLENTI
POINTEUR DDLINC.MLENTI
*inu POINTEUR DDLPT.MLENTI
POINTEUR NEWNUM.MLENTI
POINTEUR KRDDL.MLENTI
POINTEUR NNUTOT.MLENTI
POINTEUR PRMDDL.MLENTI
SEGMENT LML
POINTEUR ML(NINC).MLENTI
ENDSEGMENT
POINTEUR DDLDIM.MLENTI
POINTEUR ITTDDL.MLENTI
POINTEUR INUDDL.MLENTI
POINTEUR LDD.LML
POINTEUR LDDI.MLENTI
POINTEUR NNU.LML
POINTEUR NNUI.MLENTI
POINTEUR NNUJ.MLENTI
POINTEUR NNUK.MLENTI
POINTEUR PRM.LML
POINTEUR PRMI.MLENTI
*-INC SMLLOGI
SEGMENT MLLOGI
LOGICAL LOGI(JG)
ENDSEGMENT
POINTEUR DDLOK.MLLOGI
* POINTEUR PTLAG.MLLOGI
POINTEUR DDLLAG.MLLOGI
*
*STAT-INC SMSTAT
*
INTEGER IMPR,IRET
INTEGER IRENU
*
INTEGER ITOTPO,JTTDDL
INTEGER NTOTPO,NTTDDL
LOGICAL LLAG,LRELA
*
* Executable statements
*
IF (IMPR.GT.1) WRITE(IOIMP,*) 'Entrée dans calnu4'
*
* Construction de DDLINC : c'est un tableau d'entiers tel que :
* DDLINC(jttddl) = ordre du ddl
*
* SEGPRT,KMINCT
* SEGPRT,PMTOT
* SEGPRT,LITYP
* SEGPRT,LINIV
SEGACT KMINCT
SEGACT LITYP
SEGACT LINIV
NINC=KMINCT.LISINC(/2)
MAXNIV=0
DO IINC=1,NINC
MAXNIV=MAX(MAXNIV,LINIV.LECT(IINC))
ENDDO
*
* Construction de DDLINC et DDLPT : sorte de segment réciproque
* de KMINCT
* En fait, DDLPT est inutile pour la suite.
* Construction de DDLLAG : liste des ddl de niveau > 1
*
NTOTPO=KMINCT.NPOS(/1)-1
NTTDDL=KMINCT.NPOS(NTOTPO+1)-1
JG=NTTDDL
SEGINI DDLINC
*inu JG=NTTDDL
*inu SEGINI DDLPT
JG=NTTDDL
* Initialisé à .FALSE.
SEGINI DDLLAG
LRELA=.FALSE.
DO ITOTPO=1,NTOTPO
DO IINC=1,NINC
IPOS=KMINCT.MPOS(ITOTPO,IINC)
IF (IPOS.NE.0) THEN
JPOS=KMINCT.NPOS(ITOTPO)+IPOS-1
DDLINC.LECT(JPOS)=IINC
*inu DDLPT.LECT(JPOS)=ITOTPO
* Non ! IF (LITYP.LECT(IINC).LE.2) THEN
IF (LINIV.LECT(IINC).GE.2) THEN
DDLLAG.LOGI(JPOS)=.TRUE.
LRELA=.TRUE.
ENDIF
ENDIF
ENDDO
ENDDO
* SEGPRT,DDLINC
*inu SEGPRT,DDLPT
* SEGPRT,DDLLAG
*dbg DO ITTDDL=1,NTTDDL
*dbg CALL DDL2PI(ITTDDL,KMINCT,
*dbg $ IPT,IBI,
*dbg $ IMPR,IRET)
*dbg IF (IRET.NE.0) GOTO 9999
*dbg WRITE(IOIMP,*) 'ddl ',ITTDDL,' = IPT=',IPT,
*dbg $ ' inconnue ',KMINCT.LISINC(IBI)
*dbg ENDDO
*inu SEGSUP DDLPT
*
* Construction des tableaux d'entiers suivants :
* LDD.IINC(1..NTTINC) liste des ddl de l'inconnue iinc
* DDLINC(JTTDDL)=IINC : numéro de l'inconnue du ddl de numéro jttddl
* KRDDL(JTTDDL)=ITTINC avec LDD.IINC(ITTINC)
*
SEGINI LDD
JG=NINC
SEGINI DDLDIM
DO IINC=1,NINC
JG=0
SEGINI LDDI
LDD.ML(IINC)=LDDI
ENDDO
JG=NTTDDL
SEGINI KRDDL
DO JTTDDL=1,NTTDDL
IINC=DDLINC.LECT(JTTDDL)
LDDI=LDD.ML(IINC)
ITTINC=DDLDIM.LECT(IINC)+1
LDDI.LECT(**)=JTTDDL
KRDDL.LECT(JTTDDL)=ITTINC
DDLDIM.LECT(IINC)=ITTINC
ENDDO
C SEGPRT,DDLDIM
C SEGPRT,LDD
C DO IINC=1,NINC
C LDDI=LDD.ML(IINC)
C SEGPRT,LDDI
C ENDDO
C SEGPRT,KRDDL
*STAT CALL PRMSTA(' Préparation renume divers',MSTAT,IMPR)
*
* Obtention de la nouvelle numérotation des ddl
* In RENUME : SEGINI NNUTOT
* In RENUME : SEGDES NNUTOT
IF (IRET.NE.0) GOTO 9999
C SEGPRT,NNUTOT
*STAT CALL PRMSTA(' Après renume',MSTAT,IMPR)
*
* Construction des NNUs pour les points qui ne sont pas dans
* DDLLAG
*
SEGACT,NNUTOT
* NINC=NINC
SEGINI NNU
DO IINC=1,NINC
JG=DDLDIM.LECT(IINC)
SEGINI NNUI
NNU.ML(IINC)=NNUI
ENDDO
DO ITOTPO=1,NTOTPO
DO IINC=1,NINC
IPOS=KMINCT.MPOS(ITOTPO,IINC)
IF (IPOS.NE.0) THEN
JPOS=KMINCT.NPOS(ITOTPO)+IPOS-1
* SG 10/06/2015 IF (.NOT.DDLLAG.LOGI(JPOS)) THEN
INNU=NNUTOT.LECT(JPOS)
NNUI=NNU.ML(IINC)
KRNNUI=KRDDL.LECT(JPOS)
NNUI.LECT(KRNNUI)=INNU
* SG 10/06/2015 ENDIF
ENDIF
ENDDO
ENDDO
SEGSUP NNUTOT
* SEGPRT,NNU
* DO IINC=1,NINC
* NNUI=NNU.ML(IINC)
* SEGPRT,NNUI
* ENDDO
IF (LRELA) THEN
C
C Obtention des numéros des ddl portant sur des points
C où il n'y a que des multiplicateurs de Lagrange
C le max ou le min des ddl de niveau INIV-1 qui lui sont
C reliés
C
SEGACT PMTOT
DO INIV=2,MAXNIV
DO IINC=1,NINC
JNIV=LINIV.LECT(IINC)
IF (JNIV.EQ.INIV) THEN
JTYP=LITYP.LECT(IINC)
DO ITOTPO=1,NTOTPO
IPOS=KMINCT.MPOS(ITOTPO,IINC)
IF (IPOS.NE.0) THEN
JTTDDL=KMINCT.NPOS(ITOTPO)+IPOS-1
IF (DDLLAG.LOGI(JTTDDL)) THEN
* WRITE(IOIMP,*) 'Lagrange JTTDDL=',JTTDDL
JNNU=0
KSTRT=PMTOT.IA(JTTDDL)
KSTOP=PMTOT.IA(JTTDDL+1)-1
* WRITE(IOIMP,*) 'iniv-1=',INIV-1
* WRITE(IOIMP,*) 'kstrt=',kstrt
* WRITE(IOIMP,*) 'kstop=',kstop
DO KIND=KSTRT,KSTOP
KTTDDL=PMTOT.JA(KIND)
KINC=DDLINC.LECT(KTTDDL)
KNIV=LINIV.LECT(KINC)
* WRITE(IOIMP,*) 'kniv=',KNIV
IF (KNIV.LE.INIV-1) THEN
NNUK=NNU.ML(KINC)
KRNNUK=KRDDL.LECT(KTTDDL)
KNNU=NNUK.LECT(KRNNUK)
* WRITE(IOIMP,*) 'ok knnu=',KNNU
IF (KNNU.EQ.0) THEN
WRITE(IOIMP,*) 'Erreur trop grave'
GOTO 9999
ENDIF
IF (JNNU.EQ.0) THEN
JNNU=KNNU
ELSE
IF (JTYP.EQ.4) THEN
JNNU=MIN(JNNU,KNNU)
*! ELSEIF (JTYP.EQ.3) THEN
ELSEIF (JTYP.EQ.3.OR.JTYP.EQ.2) THEN
JNNU=MAX(JNNU,KNNU)
ELSE
WRITE(IOIMP,*) 'Erreur grave 1.2'
GOTO 9999
ENDIF
ENDIF
ENDIF
ENDDO
IF (JNNU.EQ.0) THEN
* SG 10/06/2015
* Ceci peut ne pas etre une erreur apres elimination des relations,
* il peut y avoir des multiplicateurs qui se retrouvent seuls
* ce qui n'est pas un pb s'ils ont une matrice de stabilisation pour
* eux.
* A ce moment-là, on ne change pas leur position dans le profil
* i.e on ne fait rien
* Ceci etait l'ancien debug...
if (.FALSE.) THEN
WRITE(IOIMP,*) 'INIV=',INIV
WRITE(IOIMP,*) 'IINC=',IINC
WRITE(IOIMP,*) 'JTYP=',JTYP
WRITE(IOIMP,*) 'JTTDDL=',JTTDDL
DO KIND=KSTRT,KSTOP
KTTDDL=PMTOT.JA(KIND)
WRITE(IOIMP,*) 'KTTDDL=',KTTDDL
KINC=DDLINC.LECT(KTTDDL)
KNIV=LINIV.LECT(KINC)
WRITE(IOIMP,*) 'KINC=',KINC
WRITE(IOIMP,*) 'KNIV=',KNIV
ENDDO
WRITE(IOIMP,*) 'Erreur grave 1.5'
GOTO 9999
endif
ELSE
NNUJ=NNU.ML(IINC)
KRNNUJ=KRDDL.LECT(JTTDDL)
NNUJ.LECT(KRNNUJ)=JNNU
ENDIF
ENDIF
ENDIF
ENDDO
ENDIF
ENDDO
ENDDO
SEGDES PMTOT
ENDIF
C SEGPRT,NNU
C DO IINC=1,NINC
C NNUI=NNU.ML(IINC)
C SEGPRT,NNUI
C ENDDO
SEGSUP KRDDL
SEGSUP DDLLAG
SEGSUP DDLINC
SEGDES LINIV
SEGDES LITYP
SEGDES KMINCT
*
* 1 On calcule les permutations qui permettent de trier NNU
* par ordre croissant de nouveau numéro.
*
SEGINI PRM
DO IINC=1,NINC
NTTINC=DDLDIM.LECT(IINC)
JG=NTTINC
SEGINI PRMI
PRM.ML(IINC)=PRMI
NNUI=NNU.ML(IINC)
$ IMPR,IRET)
IF (IRET.NE.0) GOTO 9999
ENDDO
C SEGPRT,PRM
C DO IORD=1,NORD
C PRMI=PRM.ML(IORD)
C SEGPRT,PRMI
C ENDDO
*
* 3 En "merge"ant les listes précédentes, on obtient
* la permutation réciproque de la nouvelle numérotation
* totale que l'on cherche (si, si !)
*
JG=NTTDDL
SEGINI PRMDDL
JG=NINC
SEGINI ITTDDL
DO IINC=1,NINC
ITTDDL.LECT(IINC)=1
ENDDO
JG=NINC
SEGINI DDLOK
DO IINC=1,NINC
DDLOK.LOGI(IINC)=(ITTDDL.LECT(IINC).LE.DDLDIM.LECT(IINC))
ENDDO
JG=NINC
SEGINI INUDDL
DO IINC=1,NINC
IF (DDLOK.LOGI(IINC)) THEN
NNUI=NNU.ML(IINC)
PRMI=PRM.ML(IINC)
* IITT=ITTDDL.LECT(IORD)
* IPRM=PRM1.LECT(IITT)
* INNU=NNU1.LECT(IPRM)
INUDDL.LECT(IINC)=NNUI.LECT(PRMI.LECT(ITTDDL.LECT(IINC)))
ENDIF
ENDDO
DO JTTDDL=1,NTTDDL
JNUMIN=0
JINC=0
DO IINC=1,NINC
IF (DDLOK.LOGI(IINC)) THEN
IF (JNUMIN.EQ.0) THEN
JNUMIN=INUDDL.LECT(IINC)
JINC=IINC
ELSE
KNUMIN=INUDDL.LECT(IINC)
IF (KNUMIN.LT.JNUMIN) THEN
JNUMIN=KNUMIN
JINC=IINC
ENDIF
ENDIF
ENDIF
ENDDO
IF ((JNUMIN.EQ.0).OR.(JINC.EQ.0)) THEN
WRITE(IOIMP,*) 'Erreur trop grave 2'
GOTO 9999
ENDIF
LDDI=LDD.ML(JINC)
NNUI=NNU.ML(JINC)
PRMI=PRM.ML(JINC)
KTTDDL=ITTDDL.LECT(JINC)
PRMDDL.LECT(JTTDDL)=LDDI.LECT(PRMI.LECT(KTTDDL))
ITTDDL.LECT(JINC)=KTTDDL+1
DDLOK.LOGI(JINC)=(ITTDDL.LECT(JINC).LE.DDLDIM.LECT(JINC))
IF (DDLOK.LOGI(JINC)) THEN
NNUI=NNU.ML(JINC)
PRMI=PRM.ML(JINC)
INUDDL.LECT(JINC)=NNUI.LECT(PRMI.LECT(ITTDDL.LECT(JINC)))
ENDIF
ENDDO
SEGSUP INUDDL
SEGSUP DDLOK
SEGSUP ITTDDL
DO IINC=1,NINC
PRMI=PRM.ML(IINC)
SEGSUP PRMI
ENDDO
SEGSUP PRM
DO IINC=1,NINC
NNUI=NNU.ML(IINC)
SEGSUP NNUI
ENDDO
SEGSUP NNU
SEGSUP DDLDIM
DO IINC=1,NINC
LDDI=LDD.ML(IINC)
SEGSUP LDDI
ENDDO
SEGSUP LDD
* SEGPRT,PRMDDL
*
* D'où la nouvelle numérotation :
*
JG=NTTDDL
SEGINI NEWNUM
SEGDES NEWNUM
SEGSUP PRMDDL
*STAT CALL PRMSTA(' Merge et obtention NEWNUM',MSTAT,IMPR)
* SEGPRT,NEWNUM
* STOP 16
*
* Normal termination
*
IRET=0
RETURN
*
* Format handling
*
*
* Error handling
*
9999 CONTINUE
IRET=1
WRITE(IOIMP,*) 'An error was detected in subroutine calnu4'
RETURN
*
* End of subroutine CALNU4
*
END
					© Cast3M 2003 - Tous droits réservés.
					Mentions légales