topv2
C TOPV2 SOURCE GOUNAND 25/11/24 21:15:20 12406 $ ,XDENS,INCMA,ISTMA,KTBES,JCAND,JNASCM,IVERI,impr,TRAVL $ ,lchtop) IMPLICIT REAL*8 (A-H,O-Z) IMPLICIT INTEGER (I-N) C*********************************************************************** C NOM : TOPV2 C DESCRIPTION : IJOB=0 C Minimise le volume d'une topologie de maillage C en le maintenant supérieur à 0 C IJOB=1 C Minimise le volume, mais on a le droit d'ajouter des C noeuds internes C IJOB=2 C La topologie de maillage est supposée être un maillage C On essaie de l'améliorer en conservant son volume C mais en augmentant sa qualité grace a l'adjonction C de noeuds internes C * 2017/11/30 : On remplace par ialgo (0 ou 1 : génération ou * optimisation de maillage) et iajno (autorise-t-on * l'algorithme à ajouter des noeuds.) 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, 05/05/2013, version initiale C HISTORIQUE : v1, 05/05/2013, création C HISTORIQUE : C HISTORIQUE : C*********************************************************************** -INC PPARAM -INC CCOPTIO -INC CCREEL -INC SMELEME * POINTEUR KELEM.MELEME POINTEUR KEXTO.MELEME POINTEUR IBTLOC.MELEME POINTEUR IPBTL2.MELEME POINTEUR KTBES.MELEME POINTEUR KTBES2.MELEME * anc POINTEUR IMCAND.MELEME -INC TMATOP1 *-INC SMELEMX POINTEUR LMCANS.MELEMX POINTEUR IPBTL.MELEMX POINTEUR KELEMX.MELEMX -INC SMLENTI *anc POINTEUR KNNO.MLENTI POINTEUR LIDXCA.MLENTI POINTEUR LOKVOL.MLENTI POINTEUR LNQUAL.MLENTI POINTEUR LINDI.MLENTI POINTEUR LINDJ.MLENTI -INC SMLREEL POINTEUR IQUAL.MLREEL POINTEUR LQUALS.MLREEL -INC SMCOORD POINTEUR KCOORD.MCOORD *-INC SMETRIQ POINTEUR KCMETR.METRIQ *-INC STRAVJ POINTEUR TRAVK.TRAVJ *-INC STRAVL * LOGICAL LOK,LDBG *anc LOGICAL LTOIBO *anc LOGICAL LTOIBA INTEGER JCAND LOGICAL LCHANG LOGICAL LCHTOP * Liste de topologies de maillages candidates * SEGMENT ITCAND(0) * Liste de topologies de maillages candidats de plus petit volume non nul * SEGMENT ITVOL(JG) * Liste de topologies de maillages candidats de plus petit volume * et de meilleure qualité * SEGMENT ILQUAL(JG) * SEGMENT ILIND(JG) * SEGMENT JLIND(JG) PARAMETER(NGRAV=3) DIMENSION XGRAV(NGRAV) PARAMETER(NMET=6) DIMENSION XMET(NMET) * * Executable statements * LDBG=.FALSE. * WRITE(IOIMP,*) 'entree topv2' IDIMP1=IDIM+1 KCOORD=TRAVK.COORD NKPVIR=TRAVK.PVIRT KEXTO=TRAVK.TOPO KCMETR=TRAVK.CMETR * LMCANS=TRAVL.MCANS LIDXCA=TRAVL.IDXCA LOKVOL=TRAVL.OKVOL LQUALS=TRAVL.QUALS * LNQUAL=TRAVL.NQUAL * LINDI=TRAVL.INDI * LINDJ=TRAVL.INDJ * IPBTL=TRAVL.PBTL * * Initialisations SEGMENT TRAVL : nb candidats=0 * nbel maillage candidats=0 * IF (IERR.NE.0) RETURN * IPOPL2=0 KTBES=KEXTO JCAND=0 * Tests sur le maillage initial : uniquement des éléments à 3 noeuds en 2D * et des éléments à 4 noeuds en 3D * SEGACT KEXTO *! NLTLOC=KEXTO.NUM(/2) NLTLOC=TRAVK.NVCOU * WRITE(IOIMP,*) 'NLTLOC=',NLTLOC IF (NLTLOC.EQ.0) GOTO 7 NBSOUS=KEXTO.LISOUS(/1) IF (NBSOUS.NE.0) THEN WRITE(IOIMP,*) 'We want only elementary meshes' GOTO 9999 ENDIF NBNN=KEXTO.NUM(/1) IF (NBNN.NE.IDIM+1) THEN WRITE(IOIMP,*) 'Only simplices are allowed' GOTO 9999 ENDIF * * IARET=KELEM.NUM(/1) * NBELEM=KELEM.NUM(/2) IARET=KELEMX.NNCOU NBELEM=KELEMX.NLCOU * write(ioimp,*) 'IARET,NBELEM=',IARET,NBELEM * segprt,KELEMX * Une vérif qu'on aurait dû faire depuis longtemps * IF (IARET.LT.0.OR.NBELEM.LT.0) THEN * IF (IARET.LE.0.OR.NBELEM.LE.0) THEN IF (IARET.LE.0.OR.NBELEM.NE.1) THEN WRITE(IOIMP,*) 'KELEMX bizarre IARET, NBELEM=',IARET,NBELEM goto 9999 ENDIF LOK=.TRUE. DO IIAR=1,IARET INOD=KELEMX.NUMX(IIAR,1) IF (INOD.EQ.0) THEN WRITE(IOIMP,*) 'KELEMX noeud nul iiar=',IIAR LOK=.FALSE. ENDIF ENDDO IF (.NOT.LOK) THEN WRITE(IOIMP,*) 'Ce cas nest pas bon du tout.' goto 9999 ENDIF * On remet les noeuds KPVIR au barycentre de KELEM (modifie le MCOORD !!!) * D'après Gruau p.32, il faudrait plutôt le remettre sur S. * Mais on pense qu'il est mieux au barycentre de KELEM * Aussi, on lui met la métrique *! 2025119 On ne le fait plus IF (NKPVIR.NE.0) THEN IF (.FALSE.) THEN DO L=1,IDIM XGRAV(L)=0.D0 ENDDO IF (KCMETR.NE.0) THEN DO ININ=1,KCMETR.XIN(/1) XMET(ININ)=0.D0 ENDDO ENDIF NPOIN=0 DO 31 IIAR=1,IARET INO=KELEMX.NUMX(IIAR,1) IF (INO.LE.NKPVIR) GOTO 31 NPOIN=NPOIN+1 IREF=IDIMP1*(INO-1) DO 5 L=1,IDIM XGRAV(L)=XGRAV(L)+KCOORD.XCOOR(IREF+L) 5 CONTINUE IF (KCMETR.NE.0) THEN if (ldbg) then write(ioimp,*) 'iiar,ino=',iiar,ino write(ioimp,*) ' coo=',(KCOORD.XCOOR(IREF+L),L=1 $ ,IDIM) write(ioimp,*) ' met=',(KCMETR.XIN(L,INO),L=1 $ ,KCMETR.XIN(/1)) endif DO 6 ININ=1,KCMETR.XIN(/1) XMET(ININ)=XMET(ININ)+KCMETR.XIN(ININ,INO) 6 CONTINUE ENDIF 31 CONTINUE if (ldbg) write(ioimp,*) 'NPOIN=',NPOIN if (ldbg) then write(ioimp,*) 'Centre de gravite' write(ioimp,*) ' coo=',(xgrav(L)/NPOIN,L=1,IDIM) if (kcmetr.ne.0) then write(ioimp,*) ' met=',(XMET(L)/NPOIN,L=1,KCMETR.XIN( $ /1)) endif endif DO IKPVIR=1,NKPVIR iref=idimp1*(ikpvir-1) do L=1,idim kcoord.xcoor(iref+L)=xgrav(L)/NPOIN enddo IF (KCMETR.NE.0) THEN DO 12 ININ=1,KCMETR.XIN(/1) KCMETR.XIN(ININ,IKPVIR)=XMET(ININ)/NPOIN 12 CONTINUE ENDIF ENDDO ENDIF * Calcul du volume de la topologie initiale * !! pour calculer le volume, il ne faut pas utiliser la métrique ! IELDEB=1 IELFIN=TRAVK.NVCOU IF (IERR.NE.0) RETURN * WRITE(IOIMP,*) 'Vomsi2 XVTLOC=',XVTLOC,' XVTLOS=',XVTLOS,' XVTLOV * $ =',XVTLOV IF (NKPVIR.GT.0) THEN if (ABS(XVTLOV).GE.XVTOL) THEN WRITE(IOIMP,*) '!! Vomsi2 XVTLOV=',XVTLOV,' XVTOL=',XVTOL write(ioimp,*) 'NVCOU=',TRAVK.NVCOU,'IELFIN=',IELFIN write(ioimp,*) 'NKPVIR=',NKPVIR segprt,kexto GOTO 7 endif ENDIF IF (IALGO.EQ.1) THEN if (ABS(XVTLOC-XVTLOS).GE.XVTOL) THEN WRITE(IOIMP,*) '!! Vomsi2 XVTLOC=',XVTLOC,' XVTLOS=',XVTLOS write(ioimp,*) 'NVCOU=',TRAVK.NVCOU,'IELFIN=',IELFIN write(ioimp,*) 'NKPVIR=',NKPVIR segprt,kexto GOTO 7 endif ENDIF * JCAND=0 * Note : on saute les topologies locales ayant un volume nul * car on n'arrivera pas à les améliorer IF (XVTLOC.LE.XVTOL) GOTO 7 * On se demandait si on devait sauter les topologies avec des * retournements... XVTLOC.NE.XVTLOS * * Génération des topologies candidates (stockage dans TRAVL: MCANS * indexé par IDXCA) * ICBES est le meilleur candidat par défaut (souvent=1, la topologie initiale) * IPOPL2 est le candidat où on a créé un nouveau noeud (souvent le * dernier, égal à travl.nccou) * * write(ioimp,*) 'Entree topv3' $ ,IPOPL2,iveri,impr) IF (IERR.NE.0) RETURN * write(ioimp,*) 'Sortie topv3' * * On a les candidats dans ITCAND * On sélectionne ceux de volume minimum non nul * JCAND=TRAVL.NCCOU if (impr.ge.4) then write(ioimp,*) 'Apres gen candidat n=',jcand endif * Sortie anticipée s'il n'y a qu'un candidat * WRITE(IOIMP,*) 'JCAND=',JCAND IF (JCAND.EQ.1) GOTO 8 * XVMIN=XVTLOC if (impr.ge.4) then write(ioimp,*) 'volume vise XVMIN=',XVMIN endif * * write(ioimp,*) 'Entree topv4' IF (IERR.NE.0) RETURN * write(ioimp,*) 'Sortie topv4' * S'il n'en reste pas (ne doit pas se produire) IF (TRAVL.NVOCOU.LE.0) THEN write(ioimp,*) 'Plus de candidats apres topv4 ???' goto 9999 * ICBES=0 * GOTO 666 ENDIF * S'il n'en reste qu'un, on peut sauter le calcul des qualités ?????? IF (TRAVL.NVOCOU.EQ.1) THEN ICBES=LOKVOL.LECT(NVOCOU) GOTO 8 ENDIF * * Les candidats ayant le bon volume sont dans ITVOL * On calcule les qualités de chaque élément des candidats et on ordonne. * * write(ioimp,*) 'Entree topv5' IF (IERR.NE.0) RETURN * write(ioimp,*) 'Sortie topv5' if (impr.ge.4) then write(ioimp,*) 'Apres calcul qualité candidats' DO i=1,NVOCOU Write(ioimp,*) 'Candidat i=',i ICAND=LOKVOL.LECT(i) IELDEB=LIDXCA.LECT(ICAND) IELFIN=LIDXCA.LECT(ICAND+1)-1 * $ ,lnqual.lect(icand)) enddo endif * * Calcul des meilleurs candidats par maximum lexical * * write(ioimp,*) 'Entree topv6' * write(ioimp,*) 'Sortie topv6' * if (impr.ge.4) then write(ioimp,*) 'Apres tri qualité candidats, le meilleur est :' $ ,icbes endif 8 CONTINUE * *anc KTBES2=KTBES ICAND=ICBES *dbg write(ioimp,*) 'icand,nccou=',icand,travl.nccou IF (ICAND.NE.1) THEN IELDEB=LIDXCA.LECT(ICAND) IELFIN=LIDXCA.LECT(ICAND+1)-1 NBNN=LMCANS.NNCOU NBELEM=IELFIN-IELDEB+1 NBSOUS=0 NBREF=0 * write(ioimp,*) 'icand,ieldeb,ielfin,nbnn,nbelem=',icand * $ ,ieldeb,ielfin,nbnn,nbelem SEGINI KTBES KTBES.ITYPEL=LMCANS.ITYPEX IDX=1 DO IEL=IELDEB,IELFIN DO INO=1,NBNN KTBES.NUM(INO,IDX)=LMCANS.NUMX(INO,IEL) ENDDO IDX=IDX+1 ENDDO ENDIF * 666 CONTINUE * Si on n'a pas sélectionné le candidat avec le noeud supplémentaire * on peut enlever le noeud *ijob IF (IJOB.EQ.1.OR.IJOB.EQ.2) THEN IF (IAJNO.NE.0) THEN IF (IPOPL2.NE.0.AND.ICBES.NE.IPOPL2) THEN NPCOUN=TRAVK.NPCOU-1 * Remise à zéro : nécessaire uniquement pour la vérification ?? if (iveri.ge.1) then IREF=(TRAVK.NPCOU-1)*IDIMP1 DO 111 I=1,IDIMP1 KCOORD.XCOOR(IREF+I)=0.D0 111 CONTINUE IF (KCMETR.NE.0) THEN DO 112 ININ=1,KCMETR.XIN(/1) KCMETR.XIN(ININ,TRAVK.NPCOU)=0.D0 112 CONTINUE ENDIF endif TRAVK.NPCOU=NPCOUN * Désactivation temporaire car pas de ménage... *tmp if (iveri.ge.2) then *tmp call vetopi(travk,'topv2 : Apres reduction travk') *tmp if (ierr.ne.0) return *tmp endif ELSE * write(ioimp,*) 'Nouveau noeud cree ','IPOPL2,ICBES,NPCOU=' * $ ,IPOPL2,ICBES,TRAVK.NPCOU * IREF=(TRAVK.NPCOU-1)*IDIMP1 * write(ioimp,*) (kcoord.xcoor(iref+iii),iii=1,idimp1) ENDIF ENDIF 7 CONTINUE IF (KEXTO.EQ.KTBES) JCAND=-JCAND IF (KEXTO.EQ.KTBES) THEN LCHTOP=.FALSE. ELSE LCHTOP=.TRUE. ENDIF * WRITE(IOIMP,*) 'sortie topv2' RETURN * * * 9999 CONTINUE MOTERR(1:8)='TOPV2 ' * 349 2 *Problème non prévu dans le s.p. %m1:8 contactez votre assistance RETURN * * End of subroutine TOPV2 * END
© Cast3M 2003 - Tous droits réservés.
Mentions légales