isova2
C ISOVA2 SOURCE CB215821 21/06/10 21:15:31 11029 IMPLICIT REAL*8 (A-H,O-Z) IMPLICIT INTEGER (I-N) C*********************************************************************** C NOM : ISOVA2 C DESCRIPTION : Construit le maillage d'une isovaleur d'un champ par C éléments C C 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, 17/12/2008, version initiale C HISTORIQUE : v1, 17/12/2008, création C HISTORIQUE : 19/12/2011, bp : ajout cub8 C HISTORIQUE : 10/09/2014, refonte + ajout du traitement 'EGSUP' C 'EGINF' sauf cub8 C HISTORIQUE : C*********************************************************************** -INC PPARAM -INC CCOPTIO -INC CCGEOME -INC SMCOORD -INC SMELEME -INC SMCHAML -INC SMLENTI * * Segments ajustables contenant les noeuds des éléments créés ainsi que * leur couleur * ELEM(1) contient des POI1 * ELEM(2) contient des SEG2 * ELEM(3) contient des TRI3 * ELEM(4) contient des TET4 * ELEM(5) contient des PYR5 * ELEM(6) contient des PRI6 * ELEM(7) contient des QUA4 * PARAMETER (NTYEL=7) SEGMENT ELEMS POINTEUR ELEM(NTYEL).MLENTI ENDSEGMENT * Défini dans isova1 INTEGER ITYPL(NTYEL) * Pile des nouveaux noeuds SEGMENT NEWNOD INTEGER NNOD INTEGER NOEINF(MAXNOD) INTEGER NOESUP(MAXNOD) REAL*8 COEINF(MAXNOD) ENDSEGMENT * LOGICAL LEGISO,LOKISO LOGICAL LPAIR PARAMETER (NMAXNO=8) REAL*8 VAL(NMAXNO),VALP(NMAXNO) LOGICAL LVALP(NMAXNO),LTRI INTEGER IPERM(NMAXNO),NUMP(NMAXNO) CHARACTER*8 MCHA INTEGER IMPR,IRET * tableaux descriptifs des cas et des aretes * pour le Marching Cubes (CUB8) PARAMETER (NMAXPT=16,NMAXCA=256,npt2=2,NMAXAR=12) INTEGER MATCAS(NMAXPT,NMAXCA),MATARE(npt2,NMAXAR) * tableaux descriptifs des cas * pour les éléments POI1, SEG2, TRI3, TET4 * * ikas pile elem * *************************** Commun à tous ******************** * 1 : rien 0 * 2 : élément total 9999 * ***************************** POI1 *************************** * 3 : noeud 1 1, 1,0 * ***************************** SEG2 *************************** *= 3 : noeud 1 1, 1,0 * 4 : noeud 2 1, 2,0 * 5 : noeud (1,2) 1, 1,2 * 6 : segment [1, k5] 2, 1,0, 5,5, * 7 : segment [k5, 2] 2, 5,5, 2,0, * ***************************** TRI3 *************************** * * 3 3 * . . * / \ / \ * / \ / \ * / \ / \ * (1,3) / \ (1,3) / \ (2,3) * .- \ .---------. * / \-- \ / \ \ * / \- \ / \ \ * / \-- \ / \ \ * / \-- \ / \ \ * 1 / \-\ 2 1 / \ \ 2 * .--------------------\. .-----------.---------. * (1,2) * *= 3 : noeud 1 1, 1,0 * 8 : noeud 3 1, 3,0 * 9 : segment [1,2] 2, 1,0, 2,0 * 10 : segment [3,2] 2, 3,0, 2,0 * 11 : segment [(1,3),2] 2, 1,3, 2,0 * 12 : triangle [1, k11] 3, 1,0, 2,0, 1,3, * 13 : triangle [ik11, 3] 3, 1,3, 2,0, 3,0, * 14 : segment [(1,3),(1,2)] 2, 1,3, 1,2 * 15 : triangle [1, ik14] 3, 1,0, 1,2, 1,3, * 16 : quadrangle [k14, 2,3] 7, 1,3, 1,2, 2,0, 3,0, * 17 : segment [(1,3),(2,3)] 2, 1,3, 2,3 * 18 : triangle [k17, 3] 3, 1,3, 2,3, 3,0, * 19 : quadrangle [1,2,ik17] 7, 1,0, 2,0, 2,3, 1,3, * ***************************** TET4 *************************** * Dur de faire des graphiques ASCII clairs en 3D. * * 4 .- * /-| \-- * / \ \-- * /- | \--- * / \ \-- * /- | \-- * / \ ---\. 2 * /- | -------/ / * / ------\-/ / * /- -------/ | / * 3 .---/ | / * \--- \ /- * \--- | / * \-- \ / * \--- | / * \---\ / * . 1 * *= 3 : noeud 1 1, 1,0 * 20 : noeud 4 1, 4,0, *= 9 : segment [1,2] 2, 1,0, 2,0 * 21 : segment [4,3] 2, 4,0, 3,0 * 22 : triangle [1,2,3] 3, 1,0, 2,0, 3,0, * 23 : triangle [4,2,3] 3, 4,0, 2,0, 3,0, * 24 : triangle [(1,4),2,3] 3, 1,4, 2,0, 3,0, * 25 : tétra [1, k24] 4, 1,0, 2,0, 3,0, 1,4, * 26 : tétra [k24, 4] 4, 1,4, 2,0, 3,0, 4,0, ****************************** * 27 : triangle [(1,4),2,(1,3)] 3, 1,4, 2,0, 1,3, * 28 : tétra [1,k27] 4, 1,0, 2,0, 1,3, 1,4, * 29 : pyra [4,3,k27] 5, 1,4, 1,3, 3,0, 4,0, 2,0, * 30 : triangle [(1,4),(2,4),3] 3, 1,4, 2,4, 3,0, * 31 : tétra [k30,4] 4, 1,4, 2,4, 3,0, 4,0, * 32 : pyra [1,2,k30] 5, 1,4, 2,4, 2,0, 1,0, 3,0, *************************************** * 33 : triangle [(1,2),(1,3),(1,4)] 3, 1,2, 1,3, 1,4, * 34 : tétra [1,k33] * 35 : prisme [k33,2,3,4] * 36 : triangle [(1,4),(2,4),(3,4)] * 37 : tétra [k36,4] * 38 : prisme [1,2,3,k36] * 39 : quadrangle [(1,4),(2,4),(2,3),(1,3)] * 40 : prisme [(1,3),(2,3),3,(1,4),(2,4),4] * 41 : prisme [1,(1,3),(1,4),2,(2,3),(2,4)] PARAMETER (NLI1=7,NLI2=12,NLI3=7,NLI4=15) PARAMETER (NLI1P=NLI1+1,NLI2P=NLI1+NLI2+1,NLI3P=NLI1+NLI2+NLI3+1) PARAMETER (NCOMAX=1+(2*6),NLIMAX=NLI1+NLI2+NLI3+NLI4) INTEGER TABDES(NCOMAX,NLIMAX) INTEGER TABDE1(NCOMAX,NLI1) INTEGER TABDE2(NCOMAX,NLI2) INTEGER TABDE3(NCOMAX,NLI3) INTEGER TABDE4(NCOMAX,NLI4) EQUIVALENCE (TABDES(1,1),TABDE1(1,1)), $ (TABDES(1,NLI1P),TABDE2(1,1)), $ (TABDES(1,NLI2P),TABDE3(1,1)), $ (TABDES(1,NLI3P),TABDE4(1,1)) * DATA TABDE1/ $ 0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, $ 9999, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, $ 1, 1,0, 0,0, 0,0, 0,0, 0,0, 0,0, $ 1, 2,0, 0,0, 0,0, 0,0, 0,0, 0,0, $ 1, 1,2, 0,0, 0,0, 0,0, 0,0, 0,0, $ 2, 1,0, 1,2, 0,0, 0,0, 0,0, 0,0, $ 2, 1,2, 2,0, 0,0, 0,0, 0,0, 0,0/ DATA TABDE2/ $ 1, 3,0, 0,0, 0,0, 0,0, 0,0, 0,0, $ 2, 1,0, 2,0, 0,0, 0,0, 0,0, 0,0, $ 2, 3,0, 2,0, 0,0, 0,0, 0,0, 0,0, $ 2, 1,3, 2,0, 0,0, 0,0, 0,0, 0,0, $ 3, 1,0, 2,0, 1,3, 0,0, 0,0, 0,0, $ 3, 1,3, 2,0, 3,0, 0,0, 0,0, 0,0, $ 2, 1,3, 1,2, 0,0, 0,0, 0,0, 0,0, $ 3, 1,0, 1,2, 1,3, 0,0, 0,0, 0,0, $ 7, 1,3, 1,2, 2,0, 3,0, 0,0, 0,0, $ 2, 1,3, 2,3, 0,0, 0,0, 0,0, 0,0, $ 3, 1,3, 2,3, 3,0, 0,0, 0,0, 0,0, $ 7, 1,0, 2,0, 2,3, 1,3, 0,0, 0,0/ DATA TABDE3/ $ 1, 4,0, 0,0, 0,0, 0,0, 0,0, 0,0, $ 2, 4,0, 3,0, 0,0, 0,0, 0,0, 0,0, $ 3, 1,0, 2,0, 3,0, 0,0, 0,0, 0,0, $ 3, 4,0, 2,0, 3,0, 0,0, 0,0, 0,0, $ 3, 1,4, 2,0, 3,0, 0,0, 0,0, 0,0, $ 4, 1,0, 2,0, 3,0, 1,4, 0,0, 0,0, $ 4, 1,4, 2,0, 3,0, 4,0, 0,0, 0,0/ DATA TABDE4/ $ 3, 1,4, 2,0, 1,3, 0,0, 0,0, 0,0, $ 4, 1,0, 2,0, 1,3, 1,4, 0,0, 0,0, $ 5, 1,4, 1,3, 3,0, 4,0, 2,0, 0,0, $ 3, 1,4, 2,4, 3,0, 0,0, 0,0, 0,0, $ 4, 1,4, 2,4, 3,0, 4,0, 0,0, 0,0, $ 5, 1,4, 2,4, 2,0, 1,0, 3,0, 0,0, $ 3, 1,2, 1,3, 1,4, 0,0, 0,0, 0,0, $ 4, 1,0, 1,2, 1,3, 1,4, 0,0, 0,0, $ 6, 1,2, 1,3, 1,4, 2,0, 3,0, 4,0, $ 3, 1,4, 2,4, 3,4, 0,0, 0,0, 0,0, $ 4, 1,4, 2,4, 3,4, 4,0, 0,0, 0,0, $ 6, 1,0, 2,0, 3,0, 1,4, 2,4, 3,4, $ 7, 1,4, 2,4, 2,3, 1,3, 0,0, 0,0, $ 6, 1,3, 2,3, 3,0, 1,4, 2,4, 4,0, $ 6, 1,0, 1,3, 1,4, 2,0, 2,3, 2,4/ * * Fonctions locales * * Cette fonction dit si on est sur une isovaleur * Cette fonction dit ok si on vérifie .GT.XISO si IOPT=1 * ou .LT.XISO si IOPT différent de 1 * (typiquement -1) LEGISO(X)=(ABS(X-XISO).LT.XTOL) * Suite à un bug du traducteur Esope, on ne peut déclarer * deux statement functions dans une subroutine. On remplace * donc celle-ci par sa valeur : * LOKISO(X)=((X.GT.XISO).EQV.(IOPT.EQ.1)) * * Executable statements * IMPR=0 IF (IMPR.GT.2) WRITE(IOIMP,*) 'Entrée dans isova2.eso' * C*********************************************************************** c Boucle sur les zones elementaires C*********************************************************************** c NNO=NUM(/1) NEL=NUM(/2) N2=IELVAL(/1) SEGACT MELVAL * Vérification de la cohérence entre la champ et la géométrie N1PTEL=VELCHE(/1) N1EL=VELCHE(/2) IF ((N1PTEL.NE.1.AND.N1PTEL.NE.NNO).OR. $ (N1EL.NE.1.AND.N1EL.NE.NEL)) THEN * 148 2 *Le champ par élément et l'objet géométrique correspondant n'ont pas le * 148 2 *même nombre de points par élément : contacter votre support RETURN ENDIF * Au maximum, on va créer quatre nouveaux noeuds par élément MAXNOC=NOEINF(/1) MAXNOD=NNOD+4*NEL IF (MAXNOD.GT.MAXNOC) SEGADJ NEWNOD C c******* Aiguillage selon type d element ******************************* c *dbg WRITE(IOIMP,*) 'ITYLOC=',ITYLOC IF (ITYLOC.GE.1.AND.ITYLOC.LE.4) GOTO 101 * IF(ITYPEL.eq.1) GOTO 101 * IF(ITYPEL.eq.2) GOTO 102 * IF(ITYPEL.eq.4) GOTO 104 * Cub8 if(ITYPEL.eq.14) goto 114 * if(ITYPEL.eq.23) goto 123 ******** Cas non traité ********************************************* MOTERR(1:4)=NOMS(ITYPEL) * 44 2 *Type d'élément inconnu %m1:4 RETURN ******** Cas des POI1, SEG2, TRI3 et TET4 101 CONTINUE NNODEL=NBNNE(ITYPEL) *dbg WRITE(IOIMP,*) 'NNODEL=',NNODEL DO IEL=1,NEL * Par defaut, il n'y a pas d'isovaleur a construire * et l'orientation est bonne IKAS=1 LPAIR=.TRUE. * Remplissage du tableau VAL, calcul du min et de max DO INODEL=1,NNODEL VAL(INODEL)=VELCHE(MIN(N1PTEL,INODEL),MIN(N1EL,IEL)) ENDDO VMIN=VAL(1) VMAX=VAL(1) DO INODEL=2,NNODEL VMIN=MIN(VMIN,VAL(INODEL)) VMAX=MAX(VMAX,VAL(INODEL)) ENDDO * WRITE(IOIMP,*) 'XISO=',XISO,' VMIN=',VMIN * $ ,' VMAX=',VMAX * Y a-t-il une isovaleur ? IF (((VMIN-XISO).LE.XTOL).AND.((VMAX-XISO).GE.-XTOL)) $ THEN * Permutation permettant d'avoir VAL en ordre croissant * VAL(IPERM(1)).LE.VAL(IPERM(2)).LE.VAL(IPERM(3)) * On garde la parité de la permutation car on va essayer d'avoir une * orientation consistante des éléments crées : * - Conserver l'orientation des éléments volumiques * - Normale aux éléments surfaciques dans le sens du gradient * *obs On ne permute pas dans le cas des SEG2 car on souhaite garder *obs l'orientation. Pour les éléments de dimension plus haute, on *obs ne garde pas l'orientation (sinon cela semble multiplier le nombre de *obs cas). DO INODEL=1,NNODEL IPERM(INODEL)=INODEL ENDDO * IF (ITYLOC.NE.2) THEN LPAIR=(MOD(NINV,2).EQ.0) * ENDIF * Write(ioimp,*) 'Iperm=',(IPERM(I),I=1,NNODEL) * Write(ioimp,*) 'Ninv=',ninv * * Nombre de points de l'élément ayant "exactement" la valeur XISO * demandee NPEQ1=0 DO INODEL=1,NNODEL VALP(INODEL)=VAL(IPERM(INODEL)) NUMP(INODEL)=NUM(IPERM(INODEL),IEL) LVALP(INODEL)=(LEGISO(VALP(INODEL))) IF (LVALP(INODEL)) THEN NPEQ1=NPEQ1+1 ENDIF ENDDO *dbg WRITE(IOIMP,*) 'NPEQ1=',NPEQ1,' XISO=',XISO,' XTOL=',XTOL ************************************************************************ ************** ********* ************** Calcul du IKAS pour chaque type d'élément ********* ************** ********* ************************************************************************ ************** ********* ************** POI1 ********* IF (ITYLOC.EQ.1) THEN IF (NPEQ1.EQ.1) THEN IKAS=2 ENDIF ************** ********* ************** ********* ************** SEG2 ********* ************** ********* ELSEIF (ITYLOC.EQ.2) THEN IF (NPEQ1.EQ.2) THEN * Le segment entier IKAS=2 ELSEIF (NPEQ1.EQ.1) THEN * Une des extrémités IF (LVALP(1)) THEN * Le premier point * ou le segment entier (IOPT.EQ.1) ET (VALP(2).GT.XISO) * ou (IOPT.EQ.-1) ET (VALP(2).LT.XISO) * IF (LOKISO(VALP(2))) THEN IF ((IOPT.NE.0).AND. $ ((VALP(2).GT.XISO).EQV.(IOPT.EQ.1))) THEN IKAS=2 ELSE IKAS=3 ENDIF ELSE * Le deuxième point * ou le segment entier (IOPT.EQ.1) ET (VALP(1).GT.XISO) * ou (IOPT.EQ.-1) ET (VALP(1).LT.XISO) * IF (LOKISO(VALP(1))) THEN IF ((IOPT.NE.0).AND. $ ((VALP(1).GT.XISO).EQV.(IOPT.EQ.1))) THEN IKAS=2 ELSE IKAS=4 ENDIF ENDIF ELSE * Un point milieu (IOPT=0) * ou un bout de segment (IOPT.NE.0) IF (IOPT.EQ.0) THEN IKAS=5 ELSE * On garde l'orientation du segment * IF (LOKISO(VALP(1))) THEN IF ((VALP(1).GT.XISO).EQV.(IOPT.EQ.1)) THEN IKAS=6 ELSE IKAS=7 ENDIF ENDIF ENDIF ************** ********* ************** TRI3 ********* ************** ********* ELSEIF (ITYLOC.EQ.3) THEN IF (NPEQ1.EQ.3) THEN * Le triangle entier IKAS=2 ELSEIF (NPEQ1.EQ.2) THEN * Un des côtés * ou le triangle entier (IOPT.EQ.1) ET (VALP(3 ou 1).GT.XISO) * (IOPT.EQ.-1) ET (VALP(3 ou 1).LT.XISO) IF (LVALP(1)) THEN IF ((IOPT.NE.0).AND. $ ((VALP(3).GT.XISO).EQV.(IOPT.EQ.1))) THEN * Le triangle entier IKAS=2 ELSE * Le segment [1,2] IKAS=9 ENDIF ELSE IF ((IOPT.NE.0).AND. $ ((VALP(1).GT.XISO).EQV.(IOPT.EQ.1))) THEN * Le triangle entier IKAS=2 ELSE * Le segment [2,3] IKAS=10 ENDIF ENDIF ELSEIF (NPEQ1.EQ.1) THEN * Un des points ou un segment * ou un des points ou le triangle ou un triangle contenant le segment IF (LVALP(1)) THEN * Le point P1 * ou le triangle entier IF ((IOPT.NE.0).AND. $ ((VALP(2).GT.XISO).EQV.(IOPT.EQ.1))) THEN * Le triangle entier IKAS=2 ELSE * 3 : noeud 1 IKAS=3 ENDIF ELSEIF (LVALP(2)) THEN * Un segment reliant P2 à l'intersection sur (P1, P3) * ou un triangle contenant ce segment (IOPT.NE.0) IF (IOPT.EQ.0) THEN * 11 : segment [2,(1,3)] IKAS=11 ELSE IF ((VALP(1).GT.XISO).EQV.(IOPT.EQ.1)) THEN * 12 : triangle [1, k11] IKAS=12 ELSE * 13 : triangle [k11, 3] IKAS=13 ENDIF ENDIF ELSE * Le point P3 * ou le triangle entier IF ((IOPT.NE.0).AND. $ ((VALP(2).GT.XISO).EQV.(IOPT.EQ.1))) THEN * Le triangle entier IKAS=2 ELSE * 8 : noeud 3 IKAS=8 ENDIF ENDIF ELSE * Un segment reliant (P1,P2) à (P1,P3) * ou (P2,P3) à (P1,P3) * ou un triangle ou un quadrangle contenant ces segments IF (IOPT.EQ.0) THEN MLENTI=ELEM(2) IF (VALP(2).GT.XISO) THEN * Un segment reliant (P1,P2) à (P1,P3) * 14 : segment [(1,2),(1,3)] IKAS=14 ELSE * Un segment reliant (P2,P3) à (P1,P3) * 17 : segment [(2,3),(1,3)] IKAS=17 ENDIF ELSE * Un triangle ou un quadrangle s'appuyant sur le * segment reliant (P1,P2) à (P1,P3) IF (VALP(2).GT.XISO) THEN IF ((VALP(1).GT.XISO).EQV.(IOPT.EQ.1)) THEN * 15 : triangle [1, k14] IKAS=15 ELSE * 16 : quadrangle [k14, 3,2] IKAS=16 ENDIF ELSE * Un triangle ou un quadrangle s'appuyant sur le * segment reliant (P2,P3) à (P1,P3) IF ((VALP(3).GT.XISO).EQV.(IOPT.EQ.1)) THEN * 18 : triangle [3, k17] IKAS=18 ELSE * 19 : quadrangle [1,2,k17] IKAS=19 ENDIF ENDIF ENDIF ENDIF ************** ********* ************** TET4 ********* ************** ********* ELSEIF (ITYLOC.EQ.4) THEN IF (NPEQ1.EQ.4) THEN * Isovaleur = tetrahedre IKAS=2 ELSEIF (NPEQ1.EQ.3) THEN * Isovaleur = 1 face du tetrahedre * ou le tetraedre entier (IOPT.EQ.1) ET (VALP(4 ou 1).GT.XISO) * (IOPT.EQ.-1) ET (VALP(4 ou 1).LT.XISO) IF (LVALP(1)) THEN IF ((IOPT.NE.0).AND. $ ((VALP(4).GT.XISO).EQV.(IOPT.EQ.1))) THEN * le tetraedre entier IKAS=2 ELSE * 22 : triangle [1,2,3] IKAS=22 ENDIF ELSE IF ((IOPT.NE.0).AND. $ ((VALP(1).GT.XISO).EQV.(IOPT.EQ.1))) THEN * le tetraedre entier IKAS=2 ELSE * 23 : triangle [2,3,4] IKAS=23 ENDIF ENDIF ELSEIF (NPEQ1.EQ.2) THEN * Isovaleur = 1 segment (P1,P2) ou (P3,P4) ou 1 triangle * appuye sur 2 points du tetrahedre (P2,P3) * ou (IOPT.NE.0) le segment ou le tétra complet * ou un tétra appuye sur le triangle appuye sur (P2,P3) * IF (LVALP(1).OR.LVALP(4)) THEN * Isovaleur = 1 segment (P1,P2) ou (P3,P4) * ou le tétra complet IF (LVALP(1)) THEN IF ((IOPT.NE.0).AND. $ ((VALP(3).GT.XISO).EQV.(IOPT.EQ.1))) THEN * le tetraedre entier IKAS=2 ELSE * 9 : segment [1,2] IKAS=9 ENDIF ELSEIF (LVALP(4)) THEN IF ((IOPT.NE.0).AND. $ ((VALP(2).GT.XISO).EQV.(IOPT.EQ.1))) THEN * le tetraedre entier IKAS=2 ELSE * 21 : segment [3,4] IKAS=21 ENDIF ELSE * Isovaleur = 1 triangle appuye sur 2 points tetra (P2,P3) * ou un tétra contenant ce triangle (IOPT.NE.0) IF (IOPT.EQ.0) THEN * 24 : triangle [2,3,(1,4)] IKAS=24 ELSE IF ((VALP(1).GT.XISO).EQV.(IOPT.EQ.1)) THEN * 25 : tétra [1, k24] IKAS=25 ELSE * 26 : tétra [k24, 4] IKAS=26 ENDIF ENDIF ENDIF ELSEIF (NPEQ1.EQ.1) THEN * Isovaleur = 1 point ou 1 triangle appuye sur 1 point du tetrahedre * ou (IOPT.NE.0) 1 point ou le tétraèdre * ou 1 tétra ou 1 pyra * IF (LVALP(1).OR.LVALP(4)) THEN * Isovaleur = 1 point ou le tétraèdre IF (LVALP(1)) THEN IF ((IOPT.NE.0).AND. $ ((VALP(2).GT.XISO).EQV.(IOPT.EQ.1))) THEN * le tetraedre entier IKAS=2 ELSE * 3 : noeud 1 IKAS=3 ENDIF ELSEIF (LVALP(4)) THEN IF ((IOPT.NE.0).AND. $ ((VALP(3).GT.XISO).EQV.(IOPT.EQ.1))) THEN * le tetraedre entier IKAS=2 ELSE * 20 : noeud 4 IKAS=20 ENDIF ELSE * Isosurface = 1 triangle appuye sur 1 point du tetrahedre * ou 1 tétra ou 1 pyra IF (LVALP(2)) THEN * Le point appuye est P2 * les autres points intersection (P1,P3) et (P1,P4) IF (IOPT.EQ.0) THEN * 27 : triangle [(1,3),(1,4),2] IKAS=27 ELSE * tétra contenant le triangle précédent et P1 IF ((VALP(1).GT.XISO).EQV.(IOPT.EQ.1)) THEN * 28 : tétra [1,k27] IKAS=28 ELSE * pyra contenant le triangle précédent et (P3,P4) (sommet P2) * 29 : pyra [4,3,k27] IKAS=29 ENDIF ENDIF ELSE * Le point appuye est P3 * les autres points intersection (P2,P4) et (P1,P4) IF (IOPT.EQ.0) THEN * 30 : triangle [(1,4),(2,4),3] IKAS=30 ELSE * tétra contenant le triangle précédent et P4 IF ((VALP(4).GT.XISO).EQV.(IOPT.EQ.1)) THEN * 31 : tétra [k30,4] IKAS=31 ELSE * pyra contenant le triangle précédent et (P1,P2) (sommet P3) * 32 : pyra [1,2,k30] IKAS=32 ENDIF ENDIF ENDIF ENDIF ELSE * Cas général : pas de point du tétra * Isosurface = 1 triangle quelconque section * du tetrahedre ou un quadrangle (= 2 triangles) * ou (IOPT.NE.0) 1 tétra ou 1 prisme s'appuyant sur le triangle * ou 1 prisme s'appuyant sur le quadrangle * * Il y toujours un point intersection * entre P1 et P4 IF (VALP(2).GT.XISO) THEN * Isosurface entre V1 et V2 * Points intersection (P1,P2) (P1,P3) (P1,P4) * Un seul triangle IF (IOPT.EQ.0) THEN * 33 : triangle [(1,2),(1,3),(1,4)] IKAS=33 ELSE * 1 tétra sommet P1 base (P1,P2) (P1,P3) (P1,P4) IF ((VALP(1).GT.XISO).EQV.(IOPT.EQ.1)) THEN * 34 : tétra [k33,1] IKAS=34 ELSE * 1 prisme base (P1,P2) (P1,P3) (P1,P4) et P2 P3 P4 * 35 : prisme [k33,2,3,4] IKAS=35 ENDIF ENDIF ELSEIF (VALP(3).LT.XISO) THEN * Isosurface entre V3 et V4 * Points intersection (P3,P4) (P2,P4) (P1,P4) * Un seul triangle IF (IOPT.EQ.0) THEN * 36 : triangle [(1,4),(2,4),(3,4)] IKAS=36 ELSE * 1 tétra sommet P4 base (P3,P4) (P2,P4) (P1,P4) IF ((VALP(4).GT.XISO).EQV.(IOPT.EQ.1)) THEN * 37 : tétra [k36,4] IKAS=37 ELSE * 1 prisme base (P3,P4) (P2,P4) (P1,P4) et P3 P2 P1 * 38 : prisme [k36,1,2,3] IKAS=38 ENDIF ENDIF ELSE * Isosurface entre V2 et V3 ; * Points intersection (P1,P3) (P2,P3) (P2,P4) (P1,P4) * Un quadrangle = 2 triangles IF (IOPT.EQ.0) THEN * 39 : quadrangle [(1,4),(2,4),(2,3),(1,3)] IKAS=39 ELSE * 1 prisme base P4 (P1,P4) (P2,P4) et P3 (P1,P3) (P2,P3) IF ((VALP(4).GT.XISO).EQV.(IOPT.EQ.1)) THEN * 40 : prisme [4,(1,4),(2,4),3,(1,3),(2,3)] IKAS=40 ELSE * 1 prisme base P1 (P1,P3) (P1,P4) et P2 (P2,P3) (P2,P4) * 41 : prisme [1,(1,3),(1,4),2,(2,3),(2,4)] IKAS=41 ENDIF ENDIF ENDIF ENDIF ************** ********* ************** Element inconnu ********* ************** ********* ELSE WRITE(IOIMP,*) 'ITYLOC=',ITYLOC GOTO 9999 ENDIF * * Doit-on garder quand même l'élément entier ? * ELSEIF (IOPT.NE.0.AND.LOKISO(VAL(1))) THEN ELSEIF (IOPT.NE.0.AND.((VAL(1).GT.XISO).EQV.(IOPT.EQ.1))) $ THEN IKAS=2 ENDIF ************************************************************************** * * Décodage du cas (IKAS) et création des éléments voulus * ************************************************************************** *dbg WRITE(IOIMP,*) 'IKAS=',IKAS * type d'élément à créer ITYL=TABDES(1,IKAS) *dbg WRITE(IOIMP,*) ' IEL=',IEL,' ITYL=',ITYL * Rien à faire IF (ITYL.EQ.0) THEN * L'élément entier, on garde la même description (orientation...) * que l'element initial (utilisation de NUM et non NUMP) ELSEIF (ITYL.EQ.9999) THEN IF (ITYL2.GE.1.AND.ITYL2.LE.NTYEL) THEN * WRITE(IOIMP,*) ' ITYPEL=',ITYPEL,' ITYL2=',ITYL2 MLENTI=ELEM(ITYL2) DO INOD=1,nbnne(itypel) * WRITE(IOIMP,*) ' INOD=',INOD, * $ ' NUM=',NUM(INOD,IEL) LECT(**)=NUM(INOD,IEL) ENDDO LECT(**)=ICOLOR(IEL) ELSE GOTO 9999 ENDIF * Ce qu'il est dit de faire dans le tableau TABDES * On utilise la description permutée (VALP, NUMP) qui a servi a calculer * IKAS * Si la permutation avait changé l'orientation LPAIR=.FALSE., * on change l'orientation de l'élément résultant ELSEIF (ITYL.GE.1.AND.ITYL.LE.NTYEL) THEN MLENTI=ELEM(ITYL) IDX=1 ITYPG=ITYPL(ITYL) NNO=NBNNE(ITYPG) *dbg write(ioimp,*) 'Element ',noms(itypg),' nb no=',nno DO INOD=1,NNO IDX=IDX+1 INO1=TABDES(IDX,IKAS) IDX=IDX+1 INO2=TABDES(IDX,IKAS) *dbg WRITE(IOIMP,*) ' INOD=',INOD,' INO1=',INO1, *dbg $ ' INO2=',INO2 IF (INO2.EQ.0) THEN LECT(**)=NUMP(INO1) ELSE VAL1=VALP(INO1) VAL2=VALP(INO2) NUM1=NUMP(INO1) NUM2=NUMP(INO2) *dbg WRITE(IOIMP,*) ' NUM1=',NUM1,' NUM2=',NUM2 *dbg WRITE(IOIMP,*) ' VAL1=',VAL1,' VAL2=',VAL2 IF (IERR.NE.0) RETURN ENDIF ENDDO LECT(**)=ICOLOR(IEL) *dbg WRITE(IOIMP,*) 'LPAIR=',LPAIR IF (.NOT.LPAIR) THEN *dbg write(ioimp,*) 'lect avant =',(lect(i),i=1,lect(/1)) * Pour les éléments simplex ou qua4, il suffit d'inverser le sens de parcours IF ((ITYL.GE.2.AND.ITYL.LE.4).OR.(ITYL.EQ.7)) THEN idfin=lect(/1)-1 iddeb=idfin-nno+1 idf=idfin-(iswap-1) idd=iddeb+(iswap-1) itmp=lect(idf) lect(idf)=lect(idd) lect(idd)=itmp enddo * Pour la pyramide, il suffit d'inverser le sens de parcours de la base carrée ELSEIF (ITYL.EQ.5) THEN idfin=lect(/1)-1-1 iddeb=idfin-(nno-1)+1 idf=idfin-(iswap-1) idd=iddeb+(iswap-1) itmp=lect(idf) lect(idf)=lect(idd) lect(idd)=itmp enddo * Pour le prisme, il faut inverser le sens de parcours des deux bases ELSEIF (ITYL.EQ.6) THEN idf2=lect(/1)-1 idd2=idf2-2 idf1=idd2-1 idd1=idf1-2 itmp=lect(idf2) lect(idf2)=lect(idd2) lect(idd2)=itmp itmp=lect(idf1) lect(idf1)=lect(idd1) lect(idd1)=itmp ENDIF *dbg write(ioimp,*) 'lect apres =',(lect(i),i=1,lect(/1)) ENDIF ELSE GOTO 9999 ENDIF ENDDO goto 900 ******** Cas des CUB8 *********************************************** 114 CONTINUE IF (IOPT.NE.0) THEN * 16 2 * Type d'élément incorrect RETURN ENDIF * On remplit les tableaux MATCAS et MATARE decrivant les cas et aretes c write(6,*) 'ISOVA2: cub8: appel a ISOVA4' c write(6,*) 'ISOVA2: MATARE=',(MATARE(iou,1),iou=1,2) c write(6,*) ' ',(MATARE(iou,2),iou=1,2) c write(6,*) ' ...' c write(6,*) 'ISOVA2: MATCAS=',(MATCAS(iou,1),iou=1,16) c write(6,*) ' ',(MATCAS(iou,2),iou=1,16) c write(6,*) ' ...' c write(6,*) ' ',(MATCAS(iou,255),iou=1,16) c write(6,*) ' ',(MATCAS(iou,256),iou=1,16) * REM (BP) : * - on ne fait pas de test avec la tolerance (cf LEGISO autres itypel) et * on espere que VAL(IVAL).le.XISO au lieu de VAL(IVAL).lt.XISO suffira. C .. * - on ne construit que des triangles TRI3 en se basant sur l algo : * "the marching cubes algorithm" (domaine public) DO 214 IEL=1,NEL ICAS = 1 DO IVAL=1,8 VAL(IVAL)=VELCHE(MIN(N1PTEL,IVAL),MIN(N1EL,IEL)) c if(VAL(IVAL).le.XISO) ICAS=ICAS+(2**(IVAL-1)) ENDDO c on teste les noeuds (attention: numerotation cub8 cast3m c differente de celle du marching cubes algorithm) if(VAL(1).le.XISO) ICAS=ICAS+1 if(VAL(4).le.XISO) ICAS=ICAS+2 if(VAL(3).le.XISO) ICAS=ICAS+4 if(VAL(2).le.XISO) ICAS=ICAS+8 if(VAL(5).le.XISO) ICAS=ICAS+16 if(VAL(8).le.XISO) ICAS=ICAS+32 if(VAL(7).le.XISO) ICAS=ICAS+64 if(VAL(6).le.XISO) ICAS=ICAS+128 c write(6,*) 'ICAS=',ICAS c write(6,*) 'MATCAS=',(MATCAS(iou,ICAS),iou=1,16) * Y a-t-il une isovaleur ? IF (ICAS.gt.1.or.ICAS.lt.256) THEN MLENTI=ELEM(3) do iar1=1,15 NUMAR1=MATCAS(iar1,ICAS) c write(6,*) 'iar1,NUMAR1=',iar1,NUMAR1 if(NUMAR1.eq.0) goto 214 ipoin1 = MATARE(1,NUMAR1) ipoin2 = MATARE(2,NUMAR1) VAL1=VAL(ipoin1) VAL2=VAL(ipoin2) NUM1=NUM(ipoin1,IEL) NUM2=NUM(ipoin2,IEL) c write(6,*) ' ipoin1 et 2 =',ipoin1,ipoin2,NUM1,NUM2 IF (IERR.NE.0) RETURN c write(6,*) ' VAL1 et 2=',VAL1,VAL2 if(mod(iar1,3).eq.0) LECT(**)=ICOLOR(IEL) enddo ENDIF 214 CONTINUE c write(6,*) '=> LECT=',(LECT(iou),iou=1,LECT(/1)) goto 900 ******** on termine proprement ************************************** 900 CONTINUE ENDDO c fin de Boucle sur les zones elementaires C*********************************************************************** RETURN * Erreur grave 9999 CONTINUE MOTERR(1:8)='ISOVA2 ' RETURN * * End of subroutine ISOVA2 * END
© Cast3M 2003 - Tous droits réservés.
Mentions légales