cmct4
C CMCT4 SOURCE GOUNAND 25/03/17 21:15:02 12207 SUBROUTINE CMCT4(IRIGC,IRIGD,IRIGB,IRIGE,IMEL,IRIG2) *_______________________________________________________________________ c c opérateur cmct option ELEM c c entrée c IRIGB : rigidité B c IRIGC : rigidité C c IRIGD : rigidité D c IMEL : maillage c c sortie c IRIG2 : rigidité contenant la matrice C* D*-1 B*t construite par c elements sur les elements de MELEME c avec C*, D*, B* les matrices reduites sur les elements de MELEME c *_______________________________________________________________________ IMPLICIT INTEGER(I-N) IMPLICIT REAL*8(A-H,O-Z) * -INC PPARAM -INC CCOPTIO -INC CCREEL -INC SMRIGID POINTEUR IRIGC.MRIGID,IRIGD.MRIGID,IRIGB.MRIGID POINTEUR IRIGC2.MRIGID,IRIGD2.MRIGID,IRIGB2.MRIGID POINTEUR IRIGE.MRIGID,IRIGE2.MRIGID POINTEUR IRIG2.MRIGID POINTEUR XMATRC.XMATRI,XMATRD.XMATRI,XMATRB.XMATRI POINTEUR XMATRE.XMATRI POINTEUR XMAT.XMATRI POINTEUR XMATV.XMATRI SEGMENT vvec(ntot) SEGMENT amat(ntot,ntot) SEGMENT amats(ntot,ntot) SEGMENT amatv(ntot,ntot) -INC SMELEME -INC CCHAMP -INC SMCOORD -INC SMCHPOI * CHARACTER*(LOCHPO) NOMINC,NOMDUA * segment icpr(nbpts) segment inode(ino) segment jelnum(imaxel,ino) segment izone(imaxel,ino) segment INFMEL integer jmel,jcpr,jnode,kelnum,jzone endsegment logical lvdec,lpivnu * lvdec=.false. nprint=40 iprint=0 lpivnu=.false. IF (IMEL.NE.0) THEN IPT1=IMEL ELSE CALL MELRIG(IRIGD,IPT1) ENDIF IF (IERR.NE.0) RETURN * * On suppose que l'objet GEOMETRIE de IRIG2 est le MELEME donne en * entree * * Etape I : reduire les matrices d'entree sur ce MELEME * puis construire les descripteurs globaux associes * nbsou=lisous(/1) C Cas d'un MELEME vide => RIGIDITE vide IF (nbsou.eq.0) THEN NRIGEL = 0 SEGINI,IRIG2 IRIG2.MTYMAT = 'KPRE' IRIG2.IFORIG = IFOUR SEGDES,IRIG2 RETURN ENDIF SEGINI INFMEL INFMEL.JMEL=MELEME * * Réduction de C sur le maillage MELEME * IRIGC2=0 CALL CMCT5(IRIGC,INFMEL,IRIGC2) IF (IERR.NE.0) RETURN * * Réduction eventuelle de B sur le maillage MELEME et sur le DESCR de C2 * IF (IRIGB.NE.IRIGC) THEN * Amélioration possible : transposition auto de B si necessaire * write(ioimp,*) ' IRIGB .NE. IRIGC' segini,irigb2=irigc2 * On enleve les xmatri nrig=irigb2.coerig(/1) do irig=1,nrig irigb2.irigel(4,irig)=0 enddo CALL CMCT5(IRIGB,INFMEL,IRIGB2) IF (IERR.NE.0) RETURN ELSE * write(ioimp,*) ' IRIGB = IRIGC' ENDIF * * Reduction de D sur le maillage MELEME et sur le DESCR primal de C2 * NRIGEL=nbsou SEGINI,IRIGD2 SEGACT,IRIGC2 DO irig=1,NRIGEL des1=irigc2.irigel(3,irig) nligrp=des1.noelep(/1) nligrd=nligrp segini des3 do iligrp=1,nligrp nno=des1.noelep(iligrp) des3.noelep(iligrp)=nno des3.noeled(iligrp)=nno nominc=des1.lisinc(iligrp) des3.lisinc(iligrp)=nominc IF (IPLA.EQ.0) THEN des3.lisdua(iligrp)=nominc ELSE des3.lisdua(iligrp)=nomdu(ipla) ENDIF enddo irigd2.irigel(3,irig)=des3 ENDDO * write(ioimp,*) ' IRIGD ' CALL CMCT5(IRIGD,INFMEL,IRIGD2) IF (IERR.NE.0) RETURN * call ecrobj('RIGIDITE',irigd2) * call ecrcha('RESU') * call prlist * return * * Reduction (eventuelle) de E sur le maillage MELEME et sur le DESCR dual de C2 * IF (IRIGE.NE.0) THEN NRIGEL=nbsou SEGINI,IRIGE2 SEGACT,IRIGC2 DO irig=1,NRIGEL des1=irigc2.irigel(3,irig) nligrd=des1.noeled(/1) nligrp=nligrd segini des3 do iligrd=1,nligrd nno=des1.noeled(iligrd) des3.noeled(iligrd)=nno des3.noelep(iligrd)=nno nomdua=des1.lisdua(iligrd) des3.lisdua(iligrd)=nomdua IF (IPLA.EQ.0) THEN des3.lisinc(iligrd)=nomdua ELSE des3.lisinc(iligrd)=nomdd(ipla) ENDIF enddo irige2.irigel(3,irig)=des3 ENDDO * write(ioimp,*) ' IRIGE ' CALL CMCT5(IRIGE,INFMEL,IRIGE2) IF (IERR.NE.0) RETURN ELSE IRIGE2=0 ENDIF * * On est pret maintenant à calculer E - C D-1 Bt * On envisage trois algorithmes : * 1) Force Brute : inversion de D puis produit * 2) Factorisation de la matrice (D Bt) = (Lu 0 ) ( Uu Upu) * (C 0 ) (Lup Lp) ( 0 Up ) * Si je comprends bien, Lp * Up = C D-1 Bt Oui ! * 3) Brute brute : d'après la formulation d'inversion, on inverse * tout, puis on inverse le bloc pp de l'inverse. Ca nous redonne le * complément de Schur * * * Algorithme factorisation LDMt: on pourrait pivoter symétriquement ? * Repris de Golub et Van Loan ! * NRIGEL=nbsou SEGINI IRIG2 SEGACT IRIGC2 DO irig=1,NRIGEL IRIG2.MTYMAT = 'KPRE' IRIG2.IFORIG = IFOUR IRIG2.COERIG(irig)=1.D0 ipt1=LISOUS(irig) IRIG2.IRIGEL(1,irig)=ipt1 des1=irigc2.irigel(3,irig) nligd=des1.noeled(/1) nligp=des1.noelep(/1) nlrig=ipt1.num(/2) * Matrice de stockage totale nligrd=nligd nligrp=nligd segini des3 do iligrd=1,nligrd nno=des1.noeled(iligrd) des3.noeled(iligrd)=nno des3.noelep(iligrd)=nno nomdua=des1.lisdua(iligrd) des3.lisdua(iligrd)=nomdua IF (IPLA.EQ.0) THEN des3.lisinc(iligrd)=nomdua ELSE des3.lisinc(iligrd)=nomdd(ipla) ENDIF enddo IRIG2.IRIGEL(3,irig)=des3 isym=2 IF (IRIGB.EQ.IRIGC) THEN IF (irigd2.irigel(7,irig).eq.0) THEN if (irige2.ne.0) then isym=irige2.irigel(7,irig) else isym=0 endif endif endif IRIG2.IRIGEL(7,irig)=isym * * Remplissage des matrices élémentaires * nelrig=nlrig segini xmatr3 xmatrd=irigd2.irigel(4,irig) * segprt,xmatrd xmatrc=irigc2.irigel(4,irig) if (irigb.ne.irigc) then xmatrb=irigb2.irigel(4,irig) else xmatrb=xmatrc endif if (irige.ne.irige) then xmatre=irige2.irigel(4,irig) else xmatre=0 endif ntot=nligp+nligd segini amat if (lvdec) then segini amats segini amatv endif segini vvec do ilrig=1,nlrig * Copies do iligp=1,nligp do iligd=1,nligp * segprt,xmatrd * write(ioimp,*) 'ilrig,iligp,iligd=',ilrig,iligp,iligd amat(iligd,iligp)=xmatrd.re(iligd,iligp,ilrig) enddo enddo do iligp=1,nligp do iligd=1,nligd amat(iligd+nligp,iligp)= $ xmatrc.re(iligd,iligp,ilrig) enddo enddo do iligp=1,nligp do iligd=1,nligd amat(iligp,iligd+nligp)= $ xmatrb.re(iligd,iligp,ilrig) enddo enddo if (xmatre.ne.0) then do iligp=1,nligd do iligd=1,nligd amat(iligp+nligp,iligd+nligp)= $ xmatre.re(iligd,iligp,ilrig) enddo enddo else do iligp=1,nligd do iligd=1,nligd amat(iligp+nligp,iligd+nligp)=0.D0 enddo enddo endif * Sauvegarde de A dans As if (lvdec) then do j=1,ntot do i=1,ntot amats(i,j)=amat(i,j) enddo enddo * segprt,amats endif * Echelle par la partie haut gauche xscahg=0.d0 do j=1,nligp xscahg=max(xscahg,amat(j,j)) enddo * xpethg positi xpethg=xscahg*xzprec*1000.d0 if (xpethg.EQ.0.d0) then write(ioimp,*) 'nrigel=',nrigel write(ioimp,*) 'ilrig,nlrig=',ilrig,nlrig write(ioimp,*) 'nligp,nligd=',nligp,nligd segprt,amat return endif * xscabd=0.d0 do j=1,nligp xest=0.d0 xpiv=max(xpethg,amat(j,j)) do i=1,nligd xest=xest-amat(i+nligp,j)*amat(j,i+nligp)/xpiv enddo xscabd=min(xscabd,xest) enddo * xpetbd negatif xpetbd=xscabd*xzprec*1000.d0 if (lvdec) then xtol=max(xpethg,abs(xpetbd))*100.d0 endif * * Factorisation de amat (LDMt ou LDLt d'apres Golub et Van Loan 3eme * edition pp. 137-139) * Amélioration possible : prendre en compte la symétrie do j=1,ntot * Résoudre L(1:1j,1:j) v(1:j) = A(1:j,j) do k=1,j vvec(k)=amat(k,j) enddo do k=1,j-1 do i=k+1,j vvec(i)=vvec(i)-vvec(k)*amat(i,k) enddo enddo * Calculer M(j,1:j-1) et stocker dans A (1:j-1,j) do i=1,j-1 amat(i,j)=vvec(i)/amat(i,i) enddo * Stocker d(j) dans A(j,j) amat(j,j)=vvec(j) if (j.le.nligp) then if (abs(amat(j,j)).lt.xpethg) then c$$$ write(ioimp,*) 'Pivot petit detecte | ',amat(j c$$$ $ ,j),' | < ',xpethg c$$$ write(ioimp,*) 'Noeud ',ipt1.num(des1.noelep(j) c$$$ $ ,ilrig), ' Inconnue ',des1.lisinc(j) amat(j,j)=xpethg lpivnu=.true. endif else if (abs(amat(j,j)).lt.-xpetbd) then c$$$ write(ioimp,*) 'Pivot petit detecte | ',amat(j c$$$ $ ,j),' | < -1* ',xpetbd c$$$ write(ioimp,*) 'Noeud ',ipt1.num(des1.noeled(j c$$$ $ -nligp),ilrig), ' Inconnue ',des1.lisdua(j c$$$ $ -nligp) amat(j,j)=xpetbd lpivnu=.true. endif endif * Calculer L(j+1:n,j) et stocker dans A (j+1:n,j) do k=1,j-1 do i=j+1,ntot amat(i,j)=amat(i,j)-vvec(k)*amat(i,k) enddo enddo do i=j+1,ntot amat(i,j)=amat(i,j)/amat(j,j) enddo enddo * Vérification de la factorisation if (lvdec) then * segprt,amat do k=1,ntot do i=1,ntot amatv(i,k)=0.D0 enddo enddo do k=1,ntot do i=1,ntot do j=1,min(i,k) xajj=amat(j,j) if (k.eq.j) then xukj=1.d0 else xukj=amat(j,k) endif if (i.eq.j) then xlij=1.d0 else xlij=amat(i,j) endif amatv(i,k)=amatv(i,k)+xlij*xajj*xukj enddo enddo enddo * segprt,amatv do k=1,ntot do i=1,ntot xda=abs(amatv(i,k)-amats(i,k)) if (xda.gt.xtol) then iprint=iprint+1 write(ioimp,*) 'Erreur factorisation detectee ' $ ,'aik=',amats(i,k),'aikv=',amatv(i,k) write(ioimp,*) 'i=',i,' k=',k write(ioimp,*) 'xpethg,xpetbd,xtol=',xpethg $ ,xpetbd,xtol write(ioimp,*) 'xda = ',xda,' > ',xtol * write(ioimp,*) 'Noeud i ',ipt1.num(des1.noelep(j) * $ ,ilrig), ' Inconnue ',des1.lisinc(j) * write(ioimp,*) 'Noeud ',ipt1.num(des1.noelep(j) * $ ,ilrig), ' Inconnue ',des1.lisinc(j) if (iprint.gt.nprint) then return endif endif enddo enddo endif * Produit LDMt avec le bloc en bas à droite et stockage dans RE * Amélioration possible : prendre en compte la symétrie do k=1,nligd k2 = nligp+k do i=1,nligd do j=1,min(i,k) if (k.eq.j) then xukj=1.d0 else endif if (i.eq.j) then xlij=1.d0 else endif xmatr3.re(i,k,ilrig)=xmatr3.re(i,k,ilrig) $ +xlij*xajj*xukj enddo enddo enddo ENDDO segsup vvec if (lvdec) then segsup amats segsup amatv endif segsup amat IRIG2.IRIGEL(4,irig)=xmatr3 IRIG2.IRIGEL(5,irig)=IRIGC2.IRIGEL(5,irig) enddo * * Menage * DO irig=1,nbsou descr=irigc2.irigel(3,irig) segsup descr xmatri=irigc2.irigel(4,irig) segsup xmatri IF (IRIGB.NE.IRIGC) THEN descr=irigb2.irigel(3,irig) segsup descr xmatri=irigb2.irigel(4,irig) segsup xmatri ENDIF descr=irigd2.irigel(3,irig) segsup descr xmatri=irigd2.irigel(4,irig) segsup xmatri IF (IRIGE.NE.0) THEN descr=irige2.irigel(3,irig) segsup descr xmatri=irige2.irigel(4,irig) segsup xmatri ENDIF ENDDO segsup irigc2 IF (IRIGB.NE.IRIGC) segsup irigb2 segsup irigd2 IF (IRIGE.NE.0) segsup irige2 * icpr=jcpr inode=jnode jelnum=kelnum izone=jzone segsup izone segsup jelnum segsup inode segsup icpr SEGSUP INFMEL * segsup meleme RETURN END
© Cast3M 2003 - Tous droits réservés.
Mentions légales