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