quali6
C QUALI6 SOURCE GOUNAND 26/01/09 21:15:51 12442 $ ,NKPVIR,XVTOL,MLREEL,NDQC,ISTRID) IMPLICIT REAL*8 (A-H,O-Z) IMPLICIT INTEGER (I-N) C*********************************************************************** C NOM : QUALI6 C DESCRIPTION : Etant donné un maillage volumique simple MELEMX, C on construit la qualité de chacun de ses éléments C dans un listreel MLREEL. C MELEMX est supposé actif. C MLREEL est rendu actif. C C Par rapport à quali2, on utilise xvtol pour mettre C le volume d'un élément à 0 s'il est petit. C Ceci est important car on utilise le signe pour dégrader la C qualité d'un élément (-1) C C Par rapport à quali3, MELEME devient un MELEMX, MLREEL est un C segment déjà existant et on introduit les éléments de début et de C fin IELDEB et IELFIN qui servent pour MELEMX ET MLREEL (qui sont C supposés de même dimension cf. trlver.eso.) * Pour MLREEL, comme on ne calcule pas la qualité des éléments * contenant le noeud virtuel, on a NDQC qui dit le nombre de qualité * calculés (IELDEB sert donc pour MELEMX et MLREEL mais IELFIN * uniquement pour MELEMX et NDQC uniquement pour MLREEL). C * Par rapport à quali5, on essaie de simplifier et de regrouper les * cas avec, sans métrique + un peu de ménage * * On introduit ISTRID, le nombre d'indicateurs renvoyés C C C C LANGAGE : ESOPE C AUTEUR : Stéphane GOUNAND (CEA/DEN/DM2S/SFME/LTMF) C mél : gounand@semt2.smts.cea.fr C*********************************************************************** C VERSION : v1, 27/11/2017, version initiale C HISTORIQUE : v1, 27/11/2017, création C HISTORIQUE : v2, 10/12/2025, on met des critères de qualité C similaires à DEDUADAP C HISTORIQUE : C*********************************************************************** -INC CCGEOME -INC PPARAM -INC CCOPTIO -INC CCREEL -INC SMCOORD -INC TMATOP1 *-INC SMETRIQ POINTEUR KCMETR.METRIQ *-INC SMELEMX -INC SMLREEL PARAMETER(NMET=6) DIMENSION XMET(NMET) * DIMENSION XMET2(2,2) * DIMENSION XMET3(3,3) DIMENSION XMETV(3,3) DIMENSION XJAC(3,3) DIMENSION XJTMJ(3,3) DIMENSION XMJ(3,3) * REAL*8 DXI(3) DIMENSION A(3,3),D(3) * Derivative of the affine barycentric map DIMENSION DABM(4,3) * Simplex node coordinates DIMENSION SNCO(3,4) DIMENSION IDXSYM(3,3,3) * * Statement functions * DISTA(A,B,C,D)=SQRT((A-C)*(A-C)+(B-D)*(B-D)) * DISTB(A,B,C,D,E,F)=SQRT((A-D)*(A-D)+(B-E)*(B-E)+(C-F)*(C-F)) * DISTA(A,B)=SQRT(A*A+B*B) * DISTB(A,B,C)=SQRT(A*A+B*B+C*C) * DETTRI(A11,A12,A21,A22)=A11*A22-A21*A12 DETTET(A11,A12,A13,A21,A22,A23,A31,A32,A33)= & A11*(A22*A33-A23*A32) & +A12*(A23*A31-A21*A33) & +A13*(A21*A32-A22*A31) * DATA ((XMETV(I,J),I=1,3),J=1,3) /9*0.D0/ DATA ((XJAC(I,J),I=1,3),J=1,3) /9*0.D0/ DATA ((XJTMJ(I,J),I=1,3),J=1,3) /9*0.D0/ DATA ((XMJ(I,J),I=1,3),J=1,3) /9*0.D0/ DATA ((A(I,J),I=1,3),J=1,3) /9*0.D0/ DATA (D(I),I=1,3) /3*0.D0/ DATA ((DABM(I,J),I=1,4),J=1,3) /12*0.D0/ DATA ((SNCO(I,J),I=1,3),J=1,4) /12*0.D0/ DATA (((IDXSYM(I,J,K),I=1,1),J=1,1),K=1,1) /1/ DATA (((IDXSYM(I,J,K),I=1,2),J=1,2),K=2,2) /1,2,2,3/ DATA (((IDXSYM(I,J,K),I=1,3),J=1,3),K=3,3) /1,2,4,2,3,5,4,5,6/ * * * Executable statements * * Choix du critère sans metrique * 1 : 2D : D(2)/D(1), XALI * 3D : D(3)/D(1), D(2)/D(1), XALI * 2 : 2D : D(2)/D(1) * 3D : D(3)/D(1), D(2)/D(1) * 3 : 2D : XALI * 3D : XALI * 4 : 2D : sort(D(2)/D(1), XALI) * 3D : sort(D(3)/D(1), D(2)/D(1), XALI) * 5 : 2D : D(2)/D(1) * 3D : D(3)/D(1) ICRIT=5 * Choix du critere avec metrique * 1 : (SORT MIN(D(I),1./D(I))), XALI, D(IDIM)/D(1) * 2 : (SORT MIN(D(I),1./D(I))), XALI * 3 : (SORT MIN(D(I),1./D(I)), XALI) * 4 : (SORT MIN(D(I),1./D(I)), D(IDIM)/D(1)) * 5 : (SORT MIN(D(I),1./D(I)), XALI, D(IDIM)/D(1)) * 6 : (SORT MIN(D(I),1./D(I))) * 7 : (SORT MIN(D(I),1./D(I)), D(IDIM)/D(1)) si SORT < 0.5 * (SORT MIN(D(I),1./D(I)), XALI) si SORT > 0.5 * 8 : (SORT_i-1 MIN(D(I),1./D(I)), D(IDIM)/D(1)) * 9 : (SORT_i-1 MIN(D(I),1./D(I)), XALI) * 10 : (SORT_i-1 MIN(D(I),1./D(I))), D(IDIM)/D(1) * 11 : (SORT_i-1 MIN(D(I),1./D(I))), XALI JCRIT=5 * write(ioimp,*) 'quali6: NKPVIR=',NKPVIR IF (IMET.EQ.0) THEN IF (ICRIT.EQ.1) THEN ISTRID=IDIM ELSEIF (ICRIT.EQ.2) THEN ISTRID=MAX(1,IDIM-1) ELSEIF (ICRIT.EQ.3.OR.ICRIT.EQ.5) THEN ISTRID=1 ELSE ISTRID=IDIM ENDIF ELSE IF ((JCRIT.EQ.1).OR.(JCRIT.EQ.5)) THEN ISTRID=IDIM+2 ELSEIF (JCRIT.EQ.6.OR.JCRIT.EQ.8.OR.JCRIT.EQ.9) THEN ISTRID=IDIM ELSE ISTRID=IDIM+1 ENDIF ENDIF NDQC=0 IF (IELDEB.GT.IELFIN) RETURN IDIMP1=IDIM+1 * NBNN=NUMX(/1) NBNN=NNCOU * NBELEM=NUMX(/2) *? JG=PROG(/1) * Trop de verif nuit... * IF (NBNN.NE.IDIMP1.OR.JG.NE.NBELEM) THEN IF (NBNN.NE.IDIMP1) THEN RETURN ENDIF IF $ (.NOT.(IELDEB.GE.1.AND.IELFIN.GE.IELDEB.AND.NLCOU.GE.IELFIN $ .AND.NUMX(/2).GE.NLCOU)) THEN WRITE(IOIMP,*) 'coucou quali6' write(ioimp,*) 'IELDEB=',IELDEB write(ioimp,*) 'IELFIN=',IELFIN write(ioimp,*) 'NLCOU=',NLCOU write(ioimp,*) 'NUM2=',NUMX(/2) write(ioimp,*) 'MELEMX=',MELEMX RETURN ENDIF * DO 10 IBELEM=1,NUMX(/2) DO 10 IBELEM=IELDEB,IELFIN * WRITE(IOIMP,*) 'IBELEM=',IBELEM * Calcul de la métrique moyenne M soit dans XMETD (scalaire) * soit dans XMETV (tenseur SPD) * Derivative of the affine barycentric map M : lambda(x) = Mx +c * Les coordonnees barycentriques sont definies par rapport au * simplex regulier de cote 1, centre sur l'origine. Le noeud sommet * a toutes ses coordonnees nulles sauf la derniere * Initialisations au premier pas IF (IBELEM.EQ.IELDEB) THEN IF (IDIM.GE.1) THEN DABM(1,1)=-1.D0 DABM(2,1)=+1.D0 IF (IDIM.GE.2) THEN DABM(1,2)=-1.D0/SQRT(3.D0) DABM(2,2)=-1.D0/SQRT(3.D0) DABM(3,2)=+2.D0/SQRT(3.D0) IF (IDIM.GE.3) THEN DABM(1,3)=-1.D0/SQRT(6.D0) DABM(2,3)=-1.D0/SQRT(6.D0) DABM(3,3)=-1.D0/SQRT(6.D0) DABM(4,3)=+3.D0/SQRT(6.D0) ENDIF ENDIF ENDIF * IF (IMET.EQ.1) XMETD=1.D0/DENSIT IF (IMET.EQ.2) XMETD=1.D0/XDENS IF (IMET.EQ.3) NFMET=1 IF (IMET.EQ.4) NFMET=IDIM*(IDIM+1)/2 ENDIF * if (imet.gt.0) then IF (IMET.GE.1.AND.IMET.LE.3) THEN IF (IMET.EQ.3) THEN YDENS=0.D0 DO I=1,IDIMP1 INO=NUMX(I,IBELEM) IF (NKPVIR.NE.0) THEN IF (INO.LE.NKPVIR) GOTO 10 ENDIF * Ici on fait la moyenne arithmétique * mais kcmetr contient le log du tenseur si imomet=1 YDENS=YDENS+KCMETR.XIN(1,INO) ENDDO YDENS=YDENS/IDIMP1 if (imomet.eq.1) then YDENS=EXP(YDENS) endif XMETD2=YDENS ELSE XMETD2=XMETD**2 ENDIF ELSEIF (IMET.EQ.4) THEN DO J=1,NFMET XMET(J)=0.D0 ENDDO DO I=1,IDIMP1 INO=NUMX(I,IBELEM) IF (NKPVIR.NE.0) THEN IF (INO.LE.NKPVIR) GOTO 10 ENDIF DO J=1,NFMET XMET(J)=XMET(J)+KCMETR.XIN(J,INO) ENDDO ENDDO DO J=1,NFMET XMET(J)=XMET(J)/IDIMP1 ENDDO * if (imomet.eq.1) then DO J=1,IDIM DO I=1,IDIM A(I,J)=XMET(IDXSYM(I,J,IDIM)) ENDDO ENDDO * Exponentielle du tenseur symétrique IOTENS=8 IKAS=3 CALL TENS2(IOTENS,IKAS,A,D,XMETV) IF (IERR.NE.0) RETURN else DO J=1,IDIM DO I=1,IDIM XMETV(I,J)=XMET(IDXSYM(I,J,IDIM)) ENDDO ENDDO endif ELSE WRITE(IOIMP,*) 'quali6 imet=',IMET RETURN ENDIF endif * Calcul du jacobien de la transformation geometrique entre * l'element regulier de coté 1 et l'element courant * Coordonnees des noeuds DO J=1,IDIMP1 INOD=NUMX(J,IBELEM) IF (NKPVIR.NE.0) THEN IF (INOD.LE.NKPVIR) goto 10 ENDIF IPNOD=(INOD-1)*IDIMP1 DO I=1,IDIM SNCO(I,J)=XCOOR(IPNOD+I) ENDDO ENDDO * write(ioimp,*) 'SNCO,I,J=',IDIM,IDIMP1 * write(ioimp,*) ((SNCO(I,J),I=1,IDIM),J=1,IDIMP1) * write(ioimp,*) 'DABM,I,J=',IDIMP1,IDIM * write(ioimp,*) ((DABM(I,J),I=1,IDIMP1),J=1,IDIM) * Matrice Jacobienne de la transformation J = SNCO*DABM DO J=1,IDIM DO I=1,IDIM XIJ=0.D0 DO K=1,IDIMP1 XIJ=XIJ+SNCO(I,K)*DABM(K,J) ENDDO XJAC(I,J)=XIJ ENDDO ENDDO IF (IDIM.EQ.1) THEN XDETJ=XJAC(1,1) ELSEIF (IDIM.EQ.2) THEN XDETJ=XJAC(1,1)*XJAC(2,2)-XJAC(2,1)*XJAC(1,2) ELSEIF (IDIM.EQ.3) THEN XDETJ=DETTET(XJAC(1,1),XJAC(1,2),XJAC(1,3),XJAC(2 $ ,1),XJAC(2,2),XJAC(2,3),XJAC(3,1),XJAC(3,2) $ ,XJAC(3,3)) ELSE INTERR(1)=IDIM RETURN ENDIF * write(ioimp,*) 'XJAC,I,J=',IDIM,IDIM * write(ioimp,*) ((XJAC(I,J),I=1,IDIM),J=1,IDIM) * Matrice JtMJ IF (IMET.LT.4) THEN DO K=1,IDIM DO I=1,IDIM XIK=0.D0 DO J=1,IDIM XIK=XIK+XJAC(J,I)*XJAC(J,K) ENDDO IF (IMET.EQ.0) THEN XJTMJ(I,K)=XIK ELSE XJTMJ(I,K)=XIK*XMETD2 ENDIF ENDDO ENDDO IF (IMET.EQ.0) THEN XDETM=1.D0 ELSE XDETM=XMETD2**IDIM ENDIF ELSE DO L=1,IDIM DO J=1,IDIM XJL=0.D0 DO K=1,IDIM * Utilisons la symetrie de XMETV XJL=XJL+XMETV(K,J)*XJAC(K,L) ENDDO XMJ(J,L)=XJL ENDDO ENDDO DO L=1,IDIM DO I=1,IDIM XIL=0.D0 DO J=1,IDIM XIL=XIL+XJAC(J,I)*XMJ(J,L) ENDDO XJTMJ(I,L)=XIL ENDDO ENDDO IF (IDIM.EQ.1) THEN XDETM=XMETV(1,1) ELSEIF (IDIM.EQ.2) THEN XDETM=XMETV(1,1)*XMETV(2,2)-XMETV(2,1)*XMETV(1,2) ELSEIF (IDIM.EQ.3) THEN XDETM=DETTET(XMETV(1,1),XMETV(1,2),XMETV(1,3),XMETV(2 $ ,1),XMETV(2,2),XMETV(2,3),XMETV(3,1),XMETV(3,2) $ ,XMETV(3,3)) ELSE INTERR(1)=IDIM RETURN ENDIF ENDIF * WRITE(IOIMP,*) 'XDETM=',XDETM * write(ioimp,*) 'XJTMJ,I,J=',IDIM,IDIM * write(ioimp,*) ((XJTMJ(I,J),I=1,IDIM),J=1,IDIM) XDETJM=XDETJ*SQRT(XDETM) * Determinant et trace de JTMJ IF (IDIM.EQ.1) THEN D(1)=XDETJM**2 ELSEIF (IDIM.EQ.2) THEN * XDET=XJTMJ(1,1)*XJTMJ(2,2)-XJTMJ(2,1)*XJTMJ(1,2) CALL JACOD2(XJTMJ,D) ELSEIF (IDIM.EQ.3) THEN * XDET=DETTET(XJTMJ(1,1),XJTMJ(1,2),XJTMJ(1,3),XJTMJ(2 * $ ,1),XJTMJ(2,2),XJTMJ(2,3),XJTMJ(3,1),XJTMJ(3,2) * $ ,XJTMJ(3,3)) ELSE WRITE(IOIMP,*) 'quali6 idim=',IDIM INTERR(1)=IDIM RETURN ENDIF XPET=XPETIT*10.D0 XTR=D(1) IF (IDIM.EQ.1) THEN XALIN1=1 ELSE DO I=2,IDIM XTR=XTR+D(I) ENDDO XL2T=XTR/IDIM IF (IDIM.EQ.2) THEN XLTD=XL2T ELSEIF (IDIM.EQ.3) THEN XLTD=XL2T*SQRT(XL2T) ELSE INTERR(1)=IDIM RETURN ENDIF XALIN1=ABS(XDETJM)/(MAX(XLTD,XPET)) * XALIN1=sqrt(max(D(IDIM)/(MAX(D(1),XPET)),xzero)) IF (IDIM.EQ.3) XALIN1=SQRT(XALIN1) ENDIF * Par rapport au livre de Huang p.205, XALIN1 vaut 1 / (Qali^(n-1)) (n>=2) * Comme Qali est minore par le rapport d'aspect d'un element, il * faut comparer XALIN1 a des (rapports de longueur)^(n-1) * Il y a donc un carre en dimension 3 cf. les expressions de XQUALN * plus bas (voir aussi deadutil.procedur qui exprime des indicateurs * en rapports de longueur) * On a choisi d'exprimer XALIN1 en fonction de XDETJM directement * car la presque nullite de XDETJ permet de detecter les elements * plats. * Si on l'eleve a la puissance (1/3), ca ne marche pas. * On devra sans doute faire mieux pour etre vraiment robuste.... * write(ioimp,*) 'XALIN1=',XALIN1 * Les valeurs propres sont censees etre positives mais pas garanti * donc on prend la valeur absolue et on reclasse JELDEB=(IELDEB-1+NDQC)*ISTRID * WRITE(IOIMP,*) '1',(D(II),II=1,IDIM) DO I=1,IDIM * D(I)=ABS(D(I)) D(I)=SQRT(MAX(D(I),XZERO)) ENDDO IF (IMET.EQ.0) THEN IF (IDIM.EQ.1) THEN ELSE IF (ICRIT.NE.3) THEN IF (ICRIT.EQ.5) THEN KMAX=1 ELSE KMAX=IDIM-1 ENDIF IF (D(1).NE.XZERO) THEN * D(1)=MAX(D(1),XPET) DO K=1,KMAX ENDDO ELSE DO K=1,KMAX ENDDO ENDIF ENDIF IF (ICRIT.NE.2) THEN ENDIF IF (ICRIT.EQ.4) THEN ENDIF ENDIF ELSE IF (JCRIT.EQ.1.OR.JCRIT.EQ.4.OR.JCRIT.EQ.5) THEN IF (D(1).NE.XZERO) THEN * PROG(JELDEB+ISTRID)=D(IDIM)/MAX(D(1),XPET) ELSE ENDIF ENDIF * WRITE(IOIMP,*) '3',(D(II),II=1,IDIM) DO K=1,IDIM XL=D(K) XLI=1.D0/MAX(D(K),XPET) D(K)=MIN(XL,XLI) * Plante avec le compilo du jour * IF (XL.GT.1.D0) THEN ** WRITE(IOIMP,*) 'XL=',XL * D(K)=1.D0/XL * ENDIF ENDDO DO K=1,IDIM ENDDO IF ((JCRIT.EQ.1).OR.(JCRIT.EQ.5)) THEN ELSEIF ((JCRIT.EQ.2).OR.(JCRIT.EQ.3)) THEN ENDIF IF ((JCRIT.EQ.1).OR.(JCRIT.EQ.2).OR.(JCRIT.GE.6)) THEN ELSEIF ((JCRIT.EQ.3).OR.(JCRIT.EQ.4)) THEN ELSEIF (JCRIT.EQ.5) THEN ENDIF IF (JCRIT.EQ.7) THEN IF (D(1).NE.XZERO) THEN ELSE ENDIF ELSE ENDIF ENDIF IF (JCRIT.EQ.8.OR.JCRIT.EQ.10) THEN IF (D(1).NE.XZERO) THEN ELSE ENDIF IF (JCRIT.EQ.8) ENDIF IF (JCRIT.EQ.9.OR.JCRIT.EQ.11) THEN IF (JCRIT.EQ.9) ENDIF ENDIF * Scaling ? mmmmm, petit doute NDQC=NDQC+1 10 CONTINUE RETURN * * formats * 188 FORMAT (2X,12(A6,'=',1PG12.5,2X)) * * End of subroutine QUALI6 * END
© Cast3M 2003 - Tous droits réservés.
Mentions légales