ldmt2
C LDMT2 SOURCE GOUNAND 24/11/12 21:15:06 12076
$ ,INCTR2,IITOP1,TRSUP,MENAGE,LDIAG,IITOPB,ITOPOB,IPODD,njtot
$ ,INORMU)
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C
C **** SUBROUTINE POUR FAIRE L'ASSEMBLAGE DE MATRICES
C
C EN ENTREE:
C **** ITRAV1 : POINTEUR OBJET MRIGIDITE
C **** ITOPO1 : POINTEUR SEGMENT DE TRAVAIL ITOPO ( VOIR ASSEM1)
C **** IITOP1 : POINTEUR SEGMENT DE TRAVAIL IITOP ( VOIR ASSEM1)
C **** INUIN1 : POINTEUR SEGMENT DE TRAVAIL INUINV(VOIR ASSEM1)
C **** IMINI1 : POINTEUR SEGMENT DE TRAVAIL IMINI (VOIR ASSEM1)
C **** IPO1 : POINTEUR SEGMENT DE TRAVAIL IPOS (VOIR ASSEM1)
C **** MMMTRI : POINTEUR OBJET MATRICE TRIANGULARISEE (NON MODIFIE)
C (VOIR SMMATRI)
C **** INORMU : =0 si on ne veut pas normaliser les multiplicateurs
C de Lagrange, <>0 sinon
C
C Appelée par : LDMT1
C
C Auteur : Michel BULIK
C
C Date : Printemps '95
C
C Langage : ESOPE + FORTRAN77
C
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
IMPLICIT INTEGER(I-N)
IMPLICIT REAL*8 (A-H,O-Z)
-INC CCREEL
-INC PPARAM
-INC CCOPTIO
-INC SMELEME
-INC SMRIGID
-INC SMMATRI
SEGMENT,INUINV(NNGLOB)
SEGMENT,ITOPO(IENNO)
SEGMENT,ITOPOB(IENNO)
SEGMENT,IITOP(NNOE+1)
SEGMENT,IITOPB(NNOE+1)
SEGMENT,IMINI(INC)
SEGMENT,IPOS(NNOE1)
SEGMENT,IPOD(NNOE1)
SEGMENT,INCTRR(NIRI)
SEGMENT,INCTRD(NIRI)
SEGMENT,INCTRA(NLIGRE)
SEGMENT,INCTRB(NLIGRE)
SEGMENT,IPV(NNOE)
SEGMENT,VMAX(INC)
C
C **** CES TABLEAUX SERVENT AU REPERAGE DE LA MATRICE POUR L'ASSEMBLAG
C **** IL SERONT TOUS SUPPRIMES EN FIN D'ASSEMBLAGE.
C
SEGMENT,IVAL(NNN)
SEGMENT,ITRA(NNN,2)
SEGMENT TRATRA
REAL*8 XTRA(INCRED,INCDIF)
INTEGER LTRA(INC,INCDIF)
INTEGER NTRA(INCRED,INCDIF)
INTEGER MTRA(INCDIF)
ENDSEGMENT
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C
C **** IVAL(I)=J : LA I EME LIGNE D'UNE PETITE MATRICE S'ASSEMBLE
C DANS LA J EME DE LA GRANDE.
C **** ITRAV(I,1)=J : LA IEME INCONNUE DU NOEUD EN COURS D'ASSEMBLAGE
C ET QUI SE TROUVE DANS LA PETITE MATRICE SE TROUVE
C EN J EME POSITION DE LA PETITE MATRICE.
C **** ITRAV(I,2) : LA IEME INCONNUE DU NOEUD EN COURS D'ASSEMBLAGE
C PRESENT DANS LA PETITE MATRICE EST EN JEME
C POSITION DANS LA GRANDE
C
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
SEGMENT,RA(N1,N1)*D
SEGMENT JNOMUL
LOGICAL INOMUL(NNR)
ENDSEGMENT
REAL*8 DMAX,COER,DDDD,DMAXY
LOGICAL NOMUL
LOGICAL TRSUP,MENAGE,LDIAG
SAVE IPASG
DATA IPASG/0/
** write(6,*) ' ldmt2 inormu ',inormu
C
C en cas de normalisation des variables.
C
C ... On a vérifié dans RESOU que dans le cas non-symétrique soit NORINC=NORIND=0,
C soit les deux sont non-nuls, mais on se méfie quand même ...
inwuit=0
C write (6,*) ' NORINC NORIND LDIAG',norinc,norind,ldiag
IF(NORINC.NE.0.AND.NORIND.NE.0 .AND. LDIAG) then
endif
C
C PV ON ACTIVE UNE FOIS POUR TOUTES LES MELEME DESCR... DE LA RIGIDITE
C ON EN PROFITE POUR CREER INOMUL
C
C **** RECHERCHE DE LA DIMENSION MAX DE IVAL,ET SEGINI DE IVAL ET ITRA
C
INCTRR=INCTR1
SEGACT,INCTRR
C ... dans le cas asymétrique on se doit de faire la même chose avec les vd ...
INCTRD=INCTR2
SEGACT,INCTRD
MRIGID=ITRAV1
SEGACT,MRIGID
NNR=IRIGEL(/2)
C ... NNR = équivalent à NRIGEL (nb. de rigidités élémentaires) ...
NNN=0
SEGINI JNOMUL
DO 1 IRI=1,NNR
INCTRA=INCTRR(IRI)
SEGACT INCTRA
C ... dans le cas asymétrique on se doit de faire la même chose avec les vd ...
INCTRB=INCTRD(IRI)
SEGACT INCTRB
DESCR=IRIGEL(3,IRI)
SEGACT, DESCR
IPT1=IRIGEL(1,IRI)
SEGACT IPT1
ipt2=IRIGEL(2,IRI)
if (ipt2.ne.0) segact,ipt2
xMATRI=IRIGEL(4,IRI)
SEGACT xMATRI
if (.not.trsup) then
C ... NA = nb de variables primales ...
NA=LISINC(/2)
else
C ... NA = nb de variables duales ...
NA=LISDUA(/2)
endif
C ... NNN = max des nb de variables primales ...
NNN=MAX(NA,NNN)
C ... INOMUL (NOn MULtiplicateurs ?) dit s'il ne s'agit pas des CL ...
INOMUL(IRI)=.TRUE.
IF(IPT1.ITYPEL.EQ.49) INOMUL(IRI)=.FALSE.
1 CONTINUE
C ... IVAL a la taille NNN ...
SEGINI,IVAL
C ... ITRA A LA TAILLE (NNN,2) ...
SEGINI,ITRA
C
C **** ACTIVATION DES SEGMENTS DE TRAVAILS ET DE MMATRI
C
IF(.NOT.LDIAG) THEN
ITOPO=ITOPO1
IITOP=IITOP1
IPOS=IPO1
ELSE
ITOPO=ITOPOB
IITOP=IITOPB
IPOS = IPODD
ENDIF
SEGACT,IITOP
SEGACT,ITOPO
SEGACT,IPOS
C write(6,*) 'ipos', ( ipos(IU),IU=1,ipos(/1))
C write(6,*) 'itopo', ( itopo(IU),IU=1,itopo(/1))
C write(6,*) 'iitop', ( iitop(IU),IU=1,iitop(/1))
INUINV=INUIN1
SEGACT,INUINV
SEGACT,IPOS
C ... NNOE = nombre de noeuds impliqués ...
NNOE=IPOS(/1)-1
C ... INC = dimension de la matrice ...
INC=IPOS(NNOE+1)
MMATRI=MMMTRI
SEGACT,MMATRI*MOD
IF(LDIAG) THEN
SEGINI,MDIAG
IDIAG=MDIAG
ELSE
MDIAG=IDIAG
SEGACT,MDIAG
ENDIF
SEGINI,MILIGN
IF(TRSUP) THEN
IILIGS=MILIGN
ELSE
IILIGN=MILIGN
ENDIF
MINCPO=IINCPO
SEGACT,MINCPO
C ... INCDIF = nb de variables primales différentes ...
INCDIF=INCPO(/1)
MIPO1=IDUAPO
SEGACT,MIPO1
casym(OK) ... on va prendre en compte aussi les vd pour déterminer
c la taille de TRATRA ...
INCDID=MIPO1.INCPO(/1)
INCDIF=MAX(INCDIF,INCDID)
*
MIMIK=IIMIK
SEGACT,MIMIK
C ... IPV est de taille NNOE ...
SEGINI IPV
INCRED=0
DO 80 INO =1,NNOE
ICOMPT=0
C ... MAXELE = nb d'éléments qui contiennent le noeud No INO ...
MAXELE = (IITOP(INO+1)-IITOP(INO))/2
C ... Boucle sur ces éléments ...
DO 81 IELE=1,MAXELE
C ... IIU = pointeur dans IITOP ...
IIU=IITOP(INO) + IELE + IELE -2
C ... IEL = numero de l'élément dans son maillage ...
IEL=ITOPO(IIU)
C ... IRI = numero du maillage (dans IRIGEL) de cet élément ...
IRI=ITOPO(IIU+1)
C ... On va chercher ce maillage dans IRIGEL ...
meleme=IRIGEL(2,IRI)
if (meleme.eq.0) meleme=IRIGEL(1,IRI)
C ... Boucle sur les noeuds de cet élément ...
DO 83 I=1,NUM(/1)
C ... IP = numéro local du I-ème noeud de l'élément ...
IP=INUINV(NUM(I,IEL))
C ... La première condition = les "connections" sont symétriques ...
IF (IP.GT.INO) GOTO 83
C ... Le noeud IP a déjà vu ce noeud ...
IF (IPV(IP).EQ.INO) GOTO 83
C ... Ces deux opérations se font si (IP <= INO et IPV(IP) != INO) ...
C ... IPV = N° max des noeuds "connectés" au noeud IP ...
IPV(IP)=INO
C ... ICOMPT = nombre de noeuds connectés (de numéro < ou =) au noeud INO ...
ICOMPT=ICOMPT+1
83 CONTINUE
81 CONTINUE
C ... INCRED = maximum des ICOMPT sur tous les noeuds impliqués ...
INCRED=MAX(INCRED,ICOMPT)
cdbg write(*,*) 'LDMT2 : Noeud ',INO,', ICOMPT = ',ICOMPT,
cdbg & ' -> INCRED = ',INCRED
80 CONTINUE
cdbg segprt,ipv
SEGSUP IPV
*
INCRED=INCRED*INCDIF
C ... La taille de TRATRA dépend de INC, INCRED et INCDIF ...
SEGINI TRATRA
segini vmax
C
C ... Coefficients de normalisation ...
C -----------------------------
LLVNUL=0
C ... On n'initialise plus IJMAX ici - ceci se fait un niveau au dessus ...
C-OLD IJMAX=0
C ... La taille de MDNOR est INC (nombre d'équations) ...
MDNOR=0
IF (LDIAG) THEN
SEGINI MDNOR
IDNORM=MDNOR
C ... On a vérifié dans RESOU que dans le cas non-symétrique soit NORINC=NORIND=0,
C soit les deux sont non-nuls ...
SEGINI,MDNO1
IDNORD=MDNO1
DO 20 I=1,INC
DNOR(I)=1.D0
MDNO1.DNOR(I)=1.D0
20 CONTINUE
else
mdnor=idnorm
segact mdnor
mdno1=idnord
segact mdno1
ENDIF
C ... Si une normalisation est imposée, les valeurs dans MDNOR et MDNO1 seront modifiées par ASNS3 ...
midua=iidua
IF(NORINC.NE.0 .AND. NORIND.NE.0 .AND. LDIAG)
C **** BOUCLE *100* SUR LES NUMEROS DE NOEUDS QUE L'ON ASSEMBLE
C -------------------------------------------------------------
DO 100 INO=1,NNOE
cdbg write(*,*) 'LDMT2: ----------------------------------'
cdbg write(*,*) 'LDMT2: Noeud N° ',INO
DO 101 IIT=1,INCDIF
MTRA(IIT)=0
101 CONTINUE
C ... Attention à l'égalité des IPOS et IPOD qui est testée dans ASNS1 ...
C ... IPRE = N° de la première ligne (ou colonne) concernée par le noeud INO ...
IPRE=IPOS(INO )+1
C ... IDER = N° de la dernière ligne (ou colonne) concernée par le noeud INO ...
IDER=IPOS(INO+1)
cdbg write(*,*) 'LDMT2: Lignes de ',IPRE,' jusqu''à ',IDER
LLVVA=0
C
C **** BOUCLE *99* SUR LES ELEMENTS TOUCHANT LE NOEUD INO
C POUR LES ELEMNTS MULTIPLICATEUR ON NE FAIT PAS
C L'ASSEMBLAGE
C
C ... MAXELE = nb d'éléments qui contiennent le noeud No INO ...
MAXELE= (IITOP(INO+1) -IITOP(INO))/2
DO 99 IELE=1,MAXELE
cdbg write(*,*) 'LDMT2: - - - - - - - - - - - -'
cdbg write(*,*) 'LDMT2: Elément N° ',IELE
IIU=IITOP(INO) + IELE + IELE - 2
C ... IEL = numero de l'élément dans son maillage ...
IEL=ITOPO(IIU)
C ... IRI = numero du maillage (dans IRIGEL) de cet élément ...
IRI=ITOPO(IIU+1)
C ... MELEME = pointeur vers ce maillage ...
MELEME=IRIGEL(1,IRI)
C ... DESCR = pointeur vers le segment DESCR concerné ...
DESCR=IRIGEL(3,IRI)
C ... INCTRA contient les indices (dans IMIK et IHAR) des descriptions
C des DDL correspondants ...
casym(OK) ... ici il faudra choisir en fonction de TRSUP si prendre INCTRR ou INCTRD ...
INCTRA=INCTRR(IRI)
INCTRB=INCTRD(IRI)
C ... xMATRI = tableau de pointeurs vers les matrices élémentaires ...
xMATRI=IRIGEL(4,IRI)
C ... COER = coefficient multiplicateur ...
COER=COERIG(IRI)
C ... NOn MULtiplicateur ? ...
NOMUL=INOMUL(IRI)
C
C **** NOMUL =.FALSE. IL EXISTE UN MULTIPLICATEUR
C **** INITIALISATION DE IVAL. IVAL(I)=J VEUT DIRE QUE
C **** LA I EME LIGNE DE LA PETITE MATRICE S'ASSEMBLE DANS
C **** LA J EME DE LA GRANDE MATRICE.
C
C ... Maintenant, dans la boucle 96 (nouvelle par rapport à ASSEM2) on
C va parcourir les lignes (colonnes) pour trouver celles, qui
C s'appuyent sur le noeud INO, cas inférieur (supérieur) ...
NA=0
IF(TRSUP) THEN
NIN=LISINC(/2)
ELSE
NIN=LISDUA(/2)
ENDIF
DO 96 ICO=1,NIN
IF(TRSUP) THEN
IJA=INUINV(NUM(NOELEP(ICO),IEL))
IJB=INCTRA(ICO)
ELSE
IJA=INUINV(NUM(NOELED(ICO),IEL))
IJB=INCTRB(ICO)
ENDIF
C ... Si on a trouvé le bon noeud ...
IF(IJA.EQ.INO) THEN
C ... On incrémente NA (le nombre de DDL connectés au noeud INO ?) ...
NA=NA+1
cdbg write(*,*) 'LDMT2: IJA == INO => NA devient ',NA
ITRA(NA,1)=ICO
IF(TRSUP) THEN
ITRA(NA,2)=INCPO(IJB,IJA)
ELSE
ITRA(NA,2)=MIPO1.INCPO(IJB,IJA)
ENDIF
ENDIF
96 CONTINUE
C ... Dans la boucle 98 on va remplir le tableau IVAL avec les numéros
C de colonnes (lignes) pour tous les DDLs primaux (duaux) de la matrice,
C ceci concerne le triangle inférieur (supérieur) ...
casym(OK) ... la boucle devra se faire soit sur les duales soit sur les primales ...
IF(TRSUP) THEN
NIN=LISDUA(/2)
ELSE
NIN=LISINC(/2)
ENDIF
C ... Boucle sur les variables primales (duales) de l'élément ...
DO 98 ICO=1,NIN
IF(TRSUP) THEN
IJA=INUINV(NUM(NOELED(ICO),IEL))
IJB=INCTRB(ICO)
IVAL(ICO)=MIPO1.INCPO(IJB,IJA)
cdbg write(*,*) 'LDMT2: vd locale N°',ICO,'-> vd globale N°',IJB
cdbg write(*,*) 'LDMT2: => N° d''équation = ',IVAL(ICO)
ELSE
C ... IJA = numéro local du noeud-support du DDL ...
casym(OK) ... ici il faudra choisir en fonction de TRSUP si prendre NOELEP ou NOELED ...
IJA=INUINV(NUM(NOELEP(ICO),IEL))
C ... IJB = indice du DDL ...
casym(OK) ... INCTRA ou INCTRB ??? ...
IJB=INCTRA(ICO)
C ... On met dans IVAL(ICO) le N° de la colonne correspondant au noeud IJA
C et DDL No IJB ...
casym(OK) ... ici il faudra choisir en fonction de TRSUP si prendre MINCPO ou MIPO1 (?) ...
IVAL(ICO)=INCPO(IJB,IJA)
cdbg write(*,*) 'LDMT2: vp locale N°',ICO,'-> vp globale N°',IJB
cdbg write(*,*) 'LDMT2: => N° de la colonne = ',IVAL(ICO)
ENDIF
98 CONTINUE
C XMATRI=IMATTT(IEL)
C SEGACT,XMATRI
cdbg segprt,xmatri
C
C **** BOUCLE *95* SUR LES INCONNUES DE LA PETITE MATRICE
C
DO 95 INCC=1,NA
C ... INCO = le N° de la ligne (cas inf.) ou colonne (cas sup.)
C du DDL dual (primal) N° INCC du noeud INO ...
casym(OK) ... ici il faudra choisir en fonction de TRSUP quoi prendre ...
C ... Boucle sur les DDL's du noeud INO ...
DO 90 IK=1,NIN
C ... IO = N° de la colonne (la ligne) correspondant au DDL N° IK de l'élément
casym(OK) ... ici il faudra choisir en fonction de TRSUP quoi prendre ...
IO=IVAL(IK)
C ... Si IO > INCO on ne fait plus rien dans cette boucle ...
C ... Car on ne parcourt que la moitié de la matrice !!! ...
C ... ILOC = N° de ligne relatif / IPRE du noeud INO ...
ILOC=INCO-IPRE+1
C ... JJ = N° (dans l'élément) de la ligne (de la colonne) correspondant au
C DDL N° INCC du noeud INO ...
casym(OK) ... attention à ce qui se passe ici ... !!!
JJ=ITRA(INCC,1)
C ... Ci-dessous on stockera les quelques lignes de la rigidité concernant le
C noeud INO dans le segment TRATRA. Les coefficients vont dans XTRA, le deuxième
C indice (ILOC) est le numéro relatif de la ligne, le premier (IMTT) n'a rien à voir avec le
C numéro de la colonne. Celui-ci est stocké dans NTRA(IMTT,ILOC). L'information inverse
C (IMTT en fonction de IO) se trouve dans LTRA(IO,ILOC). On met dans MTRA le nombre
C de termes différents assemblés par ligne ...
C ... ILTT doit contenir l'indice IMMTT en fonction du N° de la colonne; s'il est
C nul, le terme n'a pas encore été assemblé, il faudra donc initialiser ...
ILTT= LTRA(IO,ILOC)
IF(ILTT.EQ.0) THEN
C ... LLVVA est initialisé à 0 au début de la boucle 100 et sert à compter les
C termes assemblés ...
LLVVA=LLVVA+1
C ... Les MTRA sont mis à 0 au début de la boucle 100 ...
C ... Ici on incrémente MTRA(ILOC) et on met la nouvelle valeur dans IMMTT,
C qui sera le premier indice dans différents tableaux de TRATRA ...
IMMTT=MTRA(ILOC)+1
MTRA(ILOC)=IMMTT
C ... puis on initialise le nouveau terme ...
XTRA(IMMTT,ILOC)=0.D0
C ... son N° de colonne (cas inf.) ou ligne (cas supérieur) ...
NTRA(IMMTT,ILOC)=IO
C ... et l'information inverse ...
LTRA(IO,ILOC)=IMMTT
ILTT=IMMTT
ENDIF
C ... Si ce n'est pas une condition aux limites, on assemble ...
IF(NOMUL) THEN
C ... Attention ! Dans XTRA 1er indice est lié à la colonne, deuxième est le numéro
C de la ligne, tandis que dans RE c'est l'inverse ...
IF(TRSUP) THEN
C write(6,*) ' iltt iloc ' , iltt,iloc
C write(6,*) 'ik jj iel re coer ',ik,jj,iel,re(ik,jj,iel),coer
XTRA(ILTT,ILOC)=XTRA(ILTT,ILOC)+RE(IK,JJ,iel)
$ *COER
cdbg write(*,*) 'LDMT2: On rajoute le terme L',IK,', C',JJ,' soit',
cdbg & RE(IK,JJ),' à la col',IPRE+ILOC-1,' et lig',
cdbg & NTRA(ILTT,ILOC)
ELSE
C write(6,*) ' iltt iloc ' , iltt,iloc
C write(6,*) 'ik jj iel re coer ',ik,jj,iel,re(jj,ik,iel),coer
XTRA(ILTT,ILOC)=XTRA(ILTT,ILOC)+RE(JJ,IK,iel)
$ *COER
cdbg write(*,*) 'LDMT2: On rajoute le terme L',JJ,', C',IK,' soit',
cdbg & RE(JJ,IK),' à la lig',IPRE+ILOC-1,' et col',
cdbg & NTRA(ILTT,ILOC)
ENDIF
ENDIF
90 CONTINUE
95 CONTINUE
C SEGDES,XMATRI
99 CONTINUE
C
C *** COMPACTAGE DES LIGNES, EN MEME TEMPS CALCUL DE IJMAX QUI SERA
C *** LA DIMENSION MAX D'UN SEGMENT LIGN.
C *** LE SEGMENT ASSOCIE A UNE LIGNE (SEGMENT LLIGN) EST DE LA FORME :
C *** IMMMM(NA) PERMET DE SAVOIR SI UN MOUVEMENT D'ENSEMBLE SUR LA
C *** LIGNE EXISTE. IPPO(NA+1) DONNE LA POSITION DANS XXVA LA 1ERE
C *** VALEUR DE LA LIGNE .XXVA VALEUR DE LA MATRICE.
C *** LINC(I) DONNE LE NUMERO DE LA COLONNE DU IEME ELEM DE XXVA
C
C ... NA = nb de lignes concernant le noeud INO ...
NA = IDER-IPRE+1
C ... LLVNUL = somme cumulée des LLVVA ...
LLVNUL=LLVNUL+LLVVA
SEGINI,LLIGN
ILIGN(INO)=LLIGN
NBA=0
C write(6,*) ' ider ipre llvnul ino ',ider,ipre,llvnul,ino
C ... Boucle sur les DDL du noeud INO ...
DO 120 JPA=1,NA
C ... IIIN = N° de ligne du DDL N° JPA ...
IIIN=IPRE+JPA -1
C ... que l'on met au bon endroit dans IMMMM (faisant partie de LLIGN) ...
IMMMM(JPA)=IIIN
C ... IPPO(I)+1 = adresse du début (dans XXVA et LINC) des données relatives au DDL N° I ...
IPPO(JPA)=NBA
C ... Boucle sur les termes dans la ligne ...
DO 121 IPAK = 1,MTRA(JPA)
C ... IUNPAK = N° de la colonne du terme N° IPAK ...
IUNPAK=NTRA(IPAK,JPA)
C ... Pour les termes mis dans LLIGN on efface l'information sur la position dans XTRA ...
LTRA(IUNPAK,JPA)=0
C ... Compteur ++ ...
NBA=NBA+1
C ... Le N° de la colonne va dans LINC ...
LINC(NBA)=IUNPAK
C write(6,*) ' nba ipak jpa, ', nba ,ipak,jpa
C ... Transfert du XTRA (segment TRATRA) vers XXVA (segment LLIGN) ...
XXVA(NBA)=XTRA(IPAK,JPA)
vmax(iiin)=max(abs(xxva(nba)),vmax(iiin))
C ... Les termes diagonaux vont dans DIAG (segment MDIAG) ...
IF(LDIAG) THEN
C write(6,*) ' iiin nba xxva(nba)', iiin,nba,xxva(nba)
IF(IIIN.EQ.IUNPAK) DIAG(IIIN)=XXVA(NBA)
ENDIF
121 CONTINUE
120 CONTINUE
C ... Le pointeur vers la fin de la dernière ligne ...
IPPO(NA+1)= NBA
NJMAX= 0
C recherche du mini globale sur toutes les inconnues
LPA=IPRE
C ... Boucle sur les lignes relatives au noeud INO ...
DO 126 JPA=IPRE,IDER
C ... On met le N° du noeud dans IPNO (segment MILIGN) ...
IPNO(JPA)=INO
C ... IPDE et IPDF : début et fin des données relatives au DDL N° JPA dans XXVA et LINC ...
IPDE=IPPO(JPA-IPRE+1)+1
IPDF=IPPO(JPA-IPRE+2)
C ... LPA = N° mini de la colonne avec des termes non nuls dans la ligne N° JPA ...
DO 155 JHT=IPDE,IPDF
LPA=MIN(LPA,LINC(JHT))
155 CONTINUE
126 CONTINUE
DO 127 JPA=IPRE,IDER
C ... On le met dans LDEB (segment LLIGN) ...
LDEB(JPA-IPRE+1)=LPA
C ... NNA = longueur de la "skyline" ...
NNA= JPA- LPA +1
C ... NJMAX = profil cumulé sur un noeud ...
NJMAX=NJMAX+NNA
127 CONTINUE
C ... NJTOT = profil total ...
NJTOT=NJTOT+NJMAX
C ... IJMAX = (profil / noeud) maxi ...
IF(IJMAX.LT.NJMAX) IJMAX=NJMAX
SEGDES,LLIGN
100 CONTINUE
C ... Fin de la boucle sur les noeuds ...
SEGSUP TRATRA
C
C **** ON REPREND TOUTE LES MATRICES CONTENANT LES MULTIPLICATEURS
C **** POUR MULTIPLIER TOUS LEURS TERMES PAR UNE NORME ATTACHEE
C **** A CHAQUE MULTIPLICATEUR. PUIS ON LES ASSEMBLE.
C
* d'abord etablir une norme generale pour le cas ou on n'arrive pas
* a calculer la norme particuliere
DMAXGE=xpetit
DO 378 I=1,INC
** write (6,*) ' assem2 diag vmav ',diag(i),vmax(i)
** vmax(i)=max(vmax(i),abs(diag(i)))
DMAXGE=MAX(DMAXGE,abs(vmax(i)))
378 CONTINUE
if (iimpi.ne.0 )
> write (6,*) ' nb inconnues facteur multiplicatif general ',
> INC,DMAXGE
if (dmaxge.lt.xpetit/xzprec*10) dmaxge=1.d0
IENMU=0
C ... ATTENTION ! Ici commence une boucle cachée (exécutée avec un GOTO 375) ...
375 IENMU1 = IENMU
IENMU=0
C ... Boucle sur les rigidités qui calcule le nombre de matrices de blocages ...
DO 376 I=1,NNR
IF(.NOT.INOMUL(I)) IENMU=IENMU+1
376 CONTINUE
C ... S'il n'y en a pas on saute cette partie du code ...
IF( IENMU.EQ.0) GO TO 3750
C ... MIMIK contient les noms des variables primales ...
MIMIK=IIMIK
SEGACT,MIMIK
C ... Boucle sur les rigidités ...
DO 11 I=1,NNR
C ... Si celle si n'est pas une matrice de blocage on passe à la suivante ...
IF(INOMUL(I)) GO TO 11
DESCR=IRIGEL(3,I)
C ... N3 = nb de variables primales ...
N3=LISINC(/2)
COER=COERIG(I)
MELEME=IRIGEL(1,I)
INCTRA=INCTRR(I)
xMATRI=IRIGEL(4,I)
C ... N2 = nombre d'éléments dans le support géométrique ...
N2=NUM(/2)
C ... À quoi correspond ce cas ? (pas de matrices élémentaires) ...
IF (re(/3).EQ.0) THEN
INOMUL(I)=.TRUE.
GOTO 11
ENDIF
C XMATRI=IMATTT(1)
C SEGACT,XMATRI
C ... N1 = nombre de variables duales ...
C ... Pourquoi va-t-on chercher N3 dans DESCR et N1 dans RE ? ...
N1=RE(/1)
SEGINI,RA
C ... Boucle sur les éléments ...
DO 14 IEL=1,N2
C ... Boucle sur les inconnues ...
DO 15 ICO=1,N3
C ... IJA = N° local du noeud-support de l'inconnue N° ICO ...
IJA=INUINV(NUM(NOELEP(ICO),IEL))
C ... IJB = N° de l'inconnue ...
IJB=INCTRA(ICO)
C ... IVAL contient la correspondance entre le N° local du DDL
C et le N° d'équation (de ligne) correspondant ...
IVAL(ICO)=INCPO(IJB,IJA)
15 CONTINUE
C JCARDO => pour les fous qui veulent se passer de la
C normalisation des mult. de Lagrange :)
IF (INORMU.EQ.0) THEN
DMAX=1.D0
DMAXY=DMAX
ELSE
DDDD= xpetit
C ... DMAX = max des valeurs absolues des termes diagonaux correspondants
C au DDL de l'élément N° IEL ...
DMAX=xpetit
IF((.NOT.LDIAG).AND.(IDIAG.EQ.0)) THEN
C write(*,*) 'Erreur interne dans LDMT2 : MDIAG pas encore',
C & ' initialisé !!!'
RETURN
ENDIF
* la boucle suivante demarre 3 car les deux premiers sont les multiplicateurs de lagrange
DO 19 ICO=3,N3
DMAX=MAX(DMAX,vmax(IVAL(ICO)),abs(diag(ival(ico))))
19 CONTINUE
C ... AUX FINS D'EVITER DES PROBLEMES DANS LA DECOMPOSITION
if(iimpi.eq.1524) WRITE(IOIMP,7391) DMAX,DDDD,IENMU,
& IENMU1,I,IEL
7391 FORMAT(' DMAX DDDD IENMU IENMU1 I IEL',2E12.5,4I3)
IF(DMAX.LE.xpetit.AND.IENMU.NE.IENMU1
& .AND.IEL.EQ.1) GOTO 377
IF(DMAX.LE.xzprec*dmaxge) DMAX = DMAXGE
DMAX=DMAX*1.5D0
C XMATRI=IMATTT(IEL)
C SEGACT,XMATRI
C ... DMAXY = maximum des termes dans la première colonne (les 2 premiers exclus) ...
DMAXY=sqrt(xpetit)*1d5
if (norinc.eq.0) dmaxy=1.d0
* demarrage a 3 aussi. On a toujours 1 -1 sur les LX
DO ICO=3,N1
DMAXY = MAX ( DMAXY, ABS( RE(ICO,1,iel)))
enddo
* demarrage a 3 aussi. On a toujours 1 -1 sur les LX
DO iko=3,N3
DMAXY = MAX ( DMAXY, ABS( RE(1,iko,iel)))
enddo
DMAX = DMAX / DMAXY
* Attention
* on reprend le dmax du premier passage pour appliquer le meme facteur sur les lignes et les colonnes
* car le max de la ligne n'est pas forcement celui de la colinne
if (.not.ldiag) dmax=dnor(ival(1))
ENDIF
IF( IIMPI. EQ.1524 ) WRITE(IOIMP,7398) DMAX
7398 FORMAT(' facteur multiplicatif de norme ',e12.5)
C ... Copie de la matrice élémentaire fois DMAX*COER dans RA ...
DO 21 ICO=1,N1
DO 2110 IKO=1,N3
RA(ICO,IKO)=RE(ICO,IKO,iel)*DMAX*COER
2110 CONTINUE
21 CONTINUE
C ... La sous-matrice de dimension 2 est multipliée par DMAXY ...
** si on ne booste pas l'egalite des mults on a des problemes de precision sur ceux ci
if (norinc.eq.0) dmaxy=dmaxy*2.d0
RA(1,1)=RA(1,1)*DMAXY
RA(2,1)=RA(2,1)*DMAXY
RA(1,2)=RA(1,2)*DMAXY
RA(2,2)=RA(2,2)*DMAXY
C ... Mise à DMAX des DNOR correspondant aux multiplicateurs ...
IF(LDIAG) THEN
DO 22 ICO=1,2
DNOR(IVAL(ICO))=DMAX
** write (6,*) 'il dnor ',ival(ico),dnor(ival(ico))
mdno1.DNOR(IVAL(ICO))=DMAX
22 CONTINUE
ENDIF
CMB ... Je suppose que l'on s'en servira pour multiplier les composantes
C du second membre pour que les déplacements imposés soient corrects ...
C ... Boucle sur les variables primales ...
** write(6,*) 'ldmt2 trsup ',trsup
DO 24 ICO=1,N3
C ... INO = N° local du noeud ...
INO=INUINV(NUM(NOELEP(ICO),IEL))
C ... IO = N° de ligne du DDL N° ICO ...
IO=IVAL(ICO)
if (ico.eq.1) io1=io
if (ico.eq.2) io2=io
C ... LLIGN contient les lignes liées aux noeud INO ...
LLIGN=ILIGN(INO)
SEGACT,LLIGN*MOD
C ... On rajoute le terme diagonal au DIAG ...
IF(LDIAG) DIAG(IO)=DIAG(IO)+RA(ICO,ICO)
C ... IMMMM contient les N°s des lignes des DDL ...
DO 132 JLIJ=1,IMMMM(/1)
JLIJ1=JLIJ
C ... On est censé trouver le bon N° de ligne et aller au 133 ...
IF( IMMMM(JLIJ).EQ.IO) GO TO 133
132 CONTINUE
IF(IIMPI.EQ.1524) WRITE(IOIMP,7354)
7354 FORMAT( ' PREMIERE ERREUR 5')
RETURN
133 CONTINUE
C ... Deuxième niveau de boucle sur les variables primales ...
DO 26 IRO=1,N1
C ... IA = N° de colonne du DDL N° IRO ...
IA=IVAL(IRO)
C ... Cas symétrique !!! ...
IF(IA.GT.IO) GO TO 26
C ... JLD et JLT sont égaux au début et à la fin (dans XXVA et LINC)
C des données relatives au DDL N° IRO ...
JLT=IPPO(JLIJ1+1)
JLD=IPPO(JLIJ1)+1
C ... On cherche le bon N° de colonne dans LINC ...
DO 134 JL=JLD,JLT
JL1=JL
IF(LINC(JL).EQ.IA) GO TO 135
134 CONTINUE
IF(IIMPI.EQ.1524) WRITE(IOIMP,7355)
7355 FORMAT( ' DEUXIEME ERREUR 5')
RETURN
135 CONTINUE
C ... On rajoute le coefficient dans RA au XXVA correspondant ...
if(.not.trsup) then
XXVA(JL1)=XXVA(JL1)+RA(ICO,IRO)
else
XXVA(JL1)=XXVA(JL1)+RA(IRO,ICO)
endif
26 CONTINUE
SEGDES,LLIGN
24 CONTINUE
C on stocke dans ittr les couples de LX
ittr(io1)=io2
ittr(io2)=io1
C SEGDES,XMATRI
14 CONTINUE
C ... Après son assemblage, une matrice de blocage n'est plus stigmatisée comme telle ...
INOMUL(I)=.TRUE.
377 CONTINUE
SEGSUP,RA
11 CONTINUE
C ... Fin de la boucle sur les rigidités ...
GO TO 375
C ... Fin de la boucle cachée ...
3750 CONTINUE
** do i = 1,inc
** if (ittr(i).eq.0.and.diag(i).ne.vmax(i))
** > write (6,*) 'diag vmax ',i,diag(i),vmax(i)
** enddo
C ... C'est l'ménaage finaale ...
DO 18 IK=1,NNR
INCTRA=INCTRR(IK)
SEGSUP,INCTRA
ELSE
SEGDES,INCTRA
ENDIF
18 CONTINUE
C PV ON DESACTIVE TOUT
NNR=IRIGEL(/2)
DO 2 IRI=1,NNR
DESCR=IRIGEL(3,IRI)
SEGDES DESCR
IPT1=IRIGEL(1,IRI)
* SEGDES IPT1
xMATRI=IRIGEL(4,IRI)
SEGDES xMATRI
2 CONTINUE
INTERR(1)=NJTOT
c-old IF(IPASG.EQ.0) CALL ERREUR(-278)
IPASG=1
IF(IIMPI.EQ.1457) WRITE(IOIMP,4821) LLVNUL,NJTOT
4821 FORMAT(' NB DE VALEURS NON NULLES DANS LA MATRICE ',I9,/
& ' NB DE VALEURS DANS LA MATRICE ',I9)
SEGSUP,IITOP,ITOPO
C SEGSUP,IITOP
ccc SEGSUP,IMINI
SEGSUP,INUINV
C SEGSUP,ITOPO
SEGSUP,INCTRR,INCTRD
ELSE
C SEGDES,IITOP
ccc SEGDES,IMINI
c SEGDES,INUINV
C SEGDES,ITOPO
c SEGDES,INCTRR
ENDIF
segact mrigid*mod
NNR=IRIGEL(/2)
DO IRI=1,NNR
IPT2=IRIGEL(2,IRI)
IF (IPT2.NE.0) THEN
SEGSUP IPT2
IRIGEL(2,IRI)=0
ENDIF
ENDDO
segact mrigid*nomod
ENDIF
C write(6,*) ' diag'
C write(6,*) ( diag(iou),iou=1,diag(/1))
SEGDES,MDIAG
SEGDES,MIMIK
IF (MDNOR.NE.0) SEGDES,MDNOR
SEGDES,MILIGN
SEGDES,MMATRI
MMMTRI=MMATRI
SEGDES,MINCPO
SEGDES,MIPO1
SEGDES,IPOS
SEGSUP,IVAL,ITRA,JNOMUL,vmax
SEGDES,MRIGID
ELSE
SEGDES,MRIGID
ENDIF
RETURN
END
					© Cast3M 2003 - Tous droits réservés.
					Mentions légales