C Copyright(C) 1999-2020 National Technology & Engineering Solutions C of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with C NTESS, the U.S. Government retains certain rights in this software. C C See packages/seacas/LICENSE for details SUBROUTINE ZHOLE (MP, ML, MS, MR, NS, MAXNL, MAXNP, MAXPRM, NPRM, & MAXNBC, MAXSBC, KNBC, KSBC, KNUM, IPOINT, COOR, IPBOUN, ILINE, & LTYPE, NINT, FACTOR, LCON, ILBOUN, ISBOUN, ISIDE, NLPS, IFLINE, & ILLIST, ISLIST, INDXH, NPPF, IFPB, LISTPB, NLPF, IFLB, & LISTLB, NSPF, IFSB, LISTSB, LINKP, LINKL, LINKS, LINKPB, & LINKLB, LINKSB, X, Y, NID, LISTL, MARKED, NL, LSTNBC, MXND, & XN, YN, NUID, LXK, KXL, NXL, LXN, NXH, NPERIM, NNN, NNNOLD, & KKK, LLL, IAVAIL, NAVAIL, JHOLE, INSIDE, EPS, NOROOM, ERR, & AMESUR, XNOLD, YNOLD, NXKOLD, MMPOLD, LINKEG, LISTEG, BMESUR, & MLINK, NPROLD, NPNOLD, NPEOLD, NNXK, REMESH, REXMIN, REXMAX, & REYMIN, REYMAX, IDIVIS, SIZMIN, EMAX, EMIN) C*********************************************************************** C SUBROUTINE ZHOLE = REMESHES AROUND HOLE IN REGION C*********************************************************************** DIMENSION IPOINT(MP), COOR(2, MP), IPBOUN(MP) DIMENSION ILINE(ML), NINT(ML), LTYPE(ML), FACTOR(ML), LCON(3, ML) DIMENSION ILBOUN(ML), ISBOUN(ML) DIMENSION ISIDE(MS), NLPS(MS), IFLINE(MS), ILLIST(MS*3) DIMENSION ISLIST(4*MR), LINKP(2, MP), LINKL(2, ML) DIMENSION LINKS(2, MS), LISTL(MAXNL) DIMENSION X(MAXNP), Y(MAXNP), NID(MAXNP, MAXPRM), NPERIM(MAXPRM) DIMENSION LINKPB(2, MP), NPPF(MP), IFPB(MP), LISTPB(2, MP) DIMENSION LINKLB(2, ML), NLPF(ML), IFLB(ML), LISTLB(2, ML) DIMENSION LINKSB(2, ML), NSPF(ML), IFSB(ML), LISTSB(2, ML) DIMENSION LSTNBC(MAXNBC) DIMENSION XN(MXND), YN(MXND), NUID(MXND), LXK(4, MXND) DIMENSION KXL(2, 3*MXND), NXL(2, 3*MXND), LXN(4, MXND) DIMENSION NXH(MXND) DIMENSION KLIST1(20), LINES(20), NODES(4) DIMENSION AMESUR(NPEOLD), XNOLD(NPNOLD), YNOLD(NPNOLD) DIMENSION NXKOLD(NNXK, NPEOLD), MMPOLD(3, NPROLD) DIMENSION LINKEG(2, MLINK), LISTEG(4 * NPEOLD), BMESUR(NPNOLD) LOGICAL ADDLNK, CCW, DELETE, ERR, EVEN, LREAL, NOROOM, COUNT LOGICAL LPNTIN, REMESH, LCIRCL, LDEL C CHECK FOR INPUT ERRORS ERR = .FALSE. IF (NNN - NNNOLD .LE. 0) THEN CALL MESSAGE('NO NODES DEFINED IN REGION') ERR = .TRUE. C GOOD INPUT ELSE LNUM = ABS(ISLIST(INDXH)) ADDLNK = .FALSE. CALL LTSORT (ML, LINKL, LNUM, LIN, ADDLNK) LCIRCL = NS .EQ. 1 .AND. LTYPE(LIN) .EQ. 3 C CIRCULAR HOLE IF (LCIRCL) THEN CALL LTSORT (MP, LINKP, LCON(1, LIN), I1, ADDLNK) CALL LTSORT (MP, LINKP, LCON(2, LIN), I2, ADDLNK) IF (I1 .NE. I2) THEN CALL MESSAGE('CIRCULAR HOLE DOES NOT CLOSE') ERR = .TRUE. GO TO 380 END IF CALL LTSORT (MP, LINKP, LCON(3, LIN), I2, ADDLNK) XCEN = COOR(1, I2) YCEN = COOR(2, I2) RADIUS = (COOR(1, I1) - XCEN)**2 + (COOR(2, I1) - YCEN)**2 IF (RADIUS .LE. 0.0) THEN CALL MESSAGE('RADIUS HAS ZERO LENGTH') ERR = .TRUE. GO TO 380 END IF XMIN = XCEN - SQRT(RADIUS) XMAX = XCEN + SQRT(RADIUS) YMIN = YCEN - SQRT(RADIUS) YMAX = YCEN + SQRT(RADIUS) NPERV = NINT(LIN) C NON-CIRCULAR HOLE ELSE NLP1 = NL + 1 CCW = .TRUE. COUNT = .FALSE. EVEN = .FALSE. LREAL = .FALSE. CALL PERIM (MP, ML, MS, NS, MAXNL, MAXNP, MAXNBC, MAXSBC, & KNBC, KSBC, KNUM, IPOINT, COOR, IPBOUN, ILINE, LTYPE, & NINT, FACTOR, LCON, ILBOUN, ISBOUN, ISIDE, NLPS, IFLINE, & ILLIST, ISLIST(INDXH), NPPF, IFPB, LISTPB, NLPF, IFLB, & LISTLB, NSPF, IFSB, LISTSB, LINKP, LINKL, LINKS, LINKPB, & LINKLB, LINKSB, X, Y, NID(1, NPRM), NPERIM(NPRM), & LISTL(NLP1), NL1, LSTNBC, MARKED, EVEN, LREAL, ERR, CCW, & COUNT, NOROOM, AMESUR, XNOLD, YNOLD, NXKOLD, MMPOLD, & LINKEG, LISTEG, BMESUR, MLINK, NPROLD, NPNOLD, NPEOLD, & NNXK, REMESH, REXMIN, REXMAX, REYMIN, REYMAX, IDIVIS, & SIZMIN, EMAX, EMIN) IF (ERR .OR. NOROOM) GO TO 380 NPERV = NPERIM(NPRM) NPNT = NPERV XMIN = X(1) XMAX = XMIN YMIN = Y(1) YMAX = YMIN DO 100 I = 1, NPNT XCEN = XCEN + X(I) YCEN = YCEN + Y(I) XMIN = MIN(XMIN, X(I)) XMAX = MAX(XMAX, X(I)) YMIN = MIN(YMIN, Y(I)) YMAX = MAX(YMAX, Y(I)) 100 CONTINUE XCEN = XCEN/DBLE(NPNT) YCEN = YCEN/DBLE(NPNT) RADIUS = SQRT((XCEN - X(1))**2 + (YCEN - Y(1))**2) DO 110 I = 2, NPNT R = SQRT((XCEN - X(I))**2 + (YCEN - Y(I))**2) RADIUS = MIN(RADIUS, R) 110 CONTINUE END IF C INITIALIZE NODES PER (ON) HOLE DO 120 I = 1, NNN NXH(I) = 0 120 CONTINUE C DELETE EVERYTHING ATTACHED TO NODES WITHIN HOLE NEAR = 0 SMALL = 0.0 DO 130 I = NNNOLD + 1, NNN IF (XN(I) .GT. XMIN .AND. XN(I) .LT. XMAX .AND. & YN(I) .GT. YMIN .AND. YN(I) .LT. YMAX) THEN DIST = (XN(I) - XCEN)**2 + (YN(I) - YCEN)**2 IF (LCIRCL) THEN LDEL = DIST .LT. RADIUS ELSE LDEL = LPNTIN (MAXNP, X, Y, NPNT, XN(I), YN(I)) END IF IF (DIST .LT. SMALL .OR. NEAR .EQ. 0) THEN NEAR = I SMALL = DIST END IF IF (LDEL) THEN IF (NUID(I) .EQ. 0) THEN CALL DELHOL (I, MXND, LXK, KXL, NXL, LXN, NXH, & NUID, NNN, IAVAIL, NAVAIL, NOROOM, ERR) IF (NOROOM .OR. ERR) GO TO 380 C CANNOT DELETE BOUNDARY NODES ELSE CALL MESSAGE('HOLE CROSSES FIXED BOUNDARY') ERR = .TRUE. GO TO 380 END IF END IF END IF 130 CONTINUE C PROCESS SMALL CIRCLES (I.E. SMALLER THAN AN ELEMENT) IF (SMALL .GT. RADIUS) THEN CCW = .TRUE. CALL GKXN (MXND, KXL, LXN, NEAR, KS1, KLIST1, ERR) DO 150 I = 1, KS1 CALL GNXKA (MXND, XN, YN, KLIST1(I), NODES, AREA, LXK, & NXL, CCW) SUM = 0.0 DO 140 J = 1, 4 J1 = J + 1 IF (J1 .GT. 4) J1 = 1 SUM = SUM + ABS((XN(NODES(J1)) - XN(NODES(J)))*(YCEN & - YN(NODES(J))) - (XCEN - XN(NODES(J))) & *(YN(NODES(J1)) - YN(NODES(J)))) 140 CONTINUE SUM = SUM/2.0 IF (ABS((AREA - SUM)/AREA) .LT. 1.0E-4) GO TO 160 150 CONTINUE CALL MESSAGE('FAILED TO FIND ELEMENT SURROUNDING '// & 'SMALL HOLE') ERR = .TRUE. GO TO 380 160 CONTINUE DO 170 I = 1, 4 IF (NUID(NODES(I)) .EQ. 0) THEN CALL DELHOL (NODES(I), MXND, LXK, KXL, NXL, LXN, NXH, & NUID, NNN, IAVAIL, NAVAIL, NOROOM, ERR) IF (NOROOM .OR. ERR) GO TO 380 END IF 170 CONTINUE END IF C SQUARE UP BOUNDARY (DELETE INTERIOR NODES WITH ONLY TWO LINES) 180 CONTINUE DELETE = .FALSE. DO 190 I = NNNOLD + 1, NNN IF (NXH(I) .EQ. 1 .AND. NUID(I) .EQ. 0) THEN CALL GETLXN (MXND, LXN, I, LINES, NUML, ERR) IF (NUML .EQ. 2 .AND. NUID(I) .EQ. 0) THEN CALL DELHOL (I, MXND, LXK, KXL, NXL, LXN, NXH, & NUID, NNN, IAVAIL, NAVAIL, NOROOM, ERR) IF (NOROOM .OR. ERR) GO TO 380 DELETE = .TRUE. END IF END IF 190 CONTINUE IF (DELETE) GO TO 180 C GENERATE DELETED ELEMENT BOUNDARY NODE LIST NH = 0 DO 200 I = NNNOLD + 1, NNN IF (NXH(I) .GT. 0) THEN NH = NH + 1 NXH(NH) = I END IF 200 CONTINUE C ENSURE THAT THERE ARE A MINIMUM OF MIN(12, NPERV) INTERVALS C AROUND HOLE IF (NH .LT. MAX(12, NPERV)) THEN DO 210 I = NH + 1, MXND NXH(I) = 0 210 CONTINUE DO 220 I = 1, NH IF (NUID(NXH(I)) .EQ. 0) THEN CALL DELHOL (NXH(I), MXND - NH, LXK, KXL, NXL, LXN, & NXH(NH + 1), NUID, NNN, IAVAIL, NAVAIL, NOROOM, & ERR) IF (NOROOM .OR. ERR) GO TO 380 DELETE = .TRUE. ELSE I1 = NXH(I) + NH NXH(I1) = 1 END IF 220 CONTINUE IF (DELETE) THEN I1 = 0 DO 230 I = NH + 1, MXND I1 = I1 + 1 NXH(I1) = NXH(I) 230 CONTINUE GO TO 180 ELSE CALL MESSAGE & ('INTERVAL MISMATCH BETWEEN HOLE AND BOUNDARY.') CALL MESSAGE('ALL ELEMENTS DELETED.') ERR = .TRUE. GO TO 380 END IF END IF C ORDER THE INTERIOR NODE LIST DO 260 I = 1, NH - 1 CALL GETLXN (MXND, LXN, NXH(I), LINES, NUML, ERR) DO 250 J = 1, NUML J1 = NXL(2, LINES(J)) + NXL(1, LINES(J)) - NXH(I) DO 240 K = I + 1, NH IF (NXH(K) .EQ. J1) THEN NXH(K) = NXH(I + 1) NXH(I + 1) = J1 GO TO 260 END IF 240 CONTINUE 250 CONTINUE 260 CONTINUE C MAKE SURE LOOP CLOSES CALL GETLXN (MXND, LXN, NXH(NH), LINES, NUML, ERR) DO 270 J = 1, NUML J1 = NXL(2, LINES(J)) + NXL(1, LINES(J)) - NXH(NH) IF (NXH(1) .EQ. J1) THEN GO TO 280 END IF 270 CONTINUE CALL MESSAGE('HOLE PERIMETER DOES NOT CLOSE') ERR = .TRUE. GO TO 380 280 CONTINUE C MAKE SURE HOLE PERIMETER IS DEFINED COUNTER-CLOCKWISE PI = ACOS(-1.0) TWOPI = PI + PI SPIRO = 0.0 AGOLD = ATAN2(YN(NXH(1)) - YN(NXH(NH)), & XN(NXH(1)) - XN(NXH(NH))) DO 290 I = 1, NH IF (I .EQ. NH) THEN NEXT = 1 ELSE NEXT = I + 1 END IF AGNEW = ATAN2(YN(NXH(NEXT)) - YN(NXH(I)), & XN(NXH(NEXT)) - XN(NXH(I))) DIFF = AGNEW - AGOLD IF (DIFF .GT. PI) THEN DIFF = DIFF - TWOPI ELSE IF (DIFF .LT .-PI) THEN DIFF = DIFF + TWOPI END IF IF (ABS(ABS(DIFF) - PI) .LT .1.0E-3) THEN CALL MESSAGE('PERIMETER CONTAINS SWITCHBACKS') ERR = .TRUE. GO TO 380 ENDIF SPIRO = SPIRO + DIFF AGOLD = AGNEW 290 CONTINUE IF (SPIRO .LT .0.0) THEN DO 300 I = 1, NH/2 ITEMP = NXH(I) NXH(I) = NXH(NH - I + 1) NXH(NH - I + 1) = ITEMP 300 CONTINUE ELSE IF ((ABS(SPIRO) .LT .PI) .OR. & (ABS(SPIRO) .GT. (3.*PI))) THEN CALL MESSAGE & ('UNABLE TO DETERMINE CW OR CCW SENSE OF HOLE') ERR = .TRUE. GO TO 380 ENDIF C FIND THE BEST STARTING POINT ON THE CIRCULAR HOLE IF (NNN + NH .GT. MXND) THEN NOROOM = .TRUE. GO TO 380 END IF C GENERATE THE PERIMETER OF THE HOLE EVEN = .TRUE. CCW = .TRUE. LREAL = .TRUE. COUNT = .TRUE. IF (NPERV .NE. NH) THEN IF (LCIRCL) THEN NINT(LIN) = NH ELSE TDIST = 0.0 DO 310 I = 1, NL1 LNUM = LISTL(NL + I) CALL LTSORT (ML, LINKL, LNUM, LIN, ADDLNK) I1 = LCON (1, LIN) I2 = LCON (2, LIN) I3 = LCON (3, LIN) CALL LTSORT (MP, LINKP, I1, J1, ADDLNK) CALL LTSORT (MP, LINKP, I2, J2, ADDLNK) IF (I3 .NE. 0) THEN CALL LTSORT (MP, LINKP, IABS (I3), J3, ADDLNK) IF (I3 .LT. 0) J3 = -J3 ELSE J3 = 0 END IF CALL LINLEN (MP, COOR, LINKP, JHOLE, ILINE(LIN), & LTYPE(LIN), I3, J1, J2, J3, DIST, ERR) IF (ERR) GO TO 380 TDIST = TDIST + DIST 310 CONTINUE NSUM = 0 DO 320 I = 1, NL1 - 1 LNUM = LISTL(NL + I) CALL LTSORT (ML, LINKL, LNUM, LIN, ADDLNK) I1 = LCON (1, LIN) I2 = LCON (2, LIN) I3 = LCON (3, LIN) CALL LTSORT (MP, LINKP, I1, J1, ADDLNK) CALL LTSORT (MP, LINKP, I2, J2, ADDLNK) IF (I3 .NE. 0) THEN CALL LTSORT (MP, LINKP, IABS (I3), J3, ADDLNK) IF (I3 .LT. 0) J3 = -J3 ELSE J3 = 0 END IF CALL LINLEN (MP, COOR, LINKP, JHOLE, ILINE(LIN), & LTYPE(LIN), I3, J1, J2, J3, DIST, ERR) IF (ERR) GO TO 380 NINT(LIN) = INT(NH * DIST/TDIST + 0.5) NSUM = NSUM + NINT(LIN) 320 CONTINUE LNUM = LISTL(NL + NL1) CALL LTSORT (ML, LINKL, LNUM, LIN, ADDLNK) NINT(LIN) = NH - NSUM END IF CALL MESSAGE('INTERVALS MODIFIED FOR HOLE') END IF NLP1 = NL + 1 CALL PERIM (MP, ML, MS, NS, MAXNL, MAXNP, MAXNBC, MAXSBC, KNBC, & KSBC, KNUM, IPOINT, COOR, IPBOUN, ILINE, LTYPE, NINT, & FACTOR, LCON, ILBOUN, ISBOUN, ISIDE, NLPS, IFLINE, ILLIST, & ISLIST(INDXH), NPPF, IFPB, LISTPB, NLPF, IFLB, LISTLB, NSPF, & IFSB, LISTSB, LINKP, LINKL, LINKS, LINKPB, LINKLB, LINKSB, & X, Y, NID(1, NPRM), NPERIM(NPRM), LISTL(NLP1), NL1, LSTNBC, & MARKED, EVEN, LREAL, ERR, CCW, COUNT, NOROOM, AMESUR, XNOLD, & YNOLD, NXKOLD, MMPOLD, LINKEG, LISTEG, BMESUR, MLINK, & NPROLD, NPNOLD, NPEOLD, NNXK, REMESH, REXMIN, REXMAX, & REYMIN, REYMAX, IDIVIS, SIZMIN, EMAX, EMIN) IF (NOROOM .OR. ERR) GO TO 380 IF (NL1 .GE. 0 .AND. NL + NL1 .LE. MAXNL) THEN NL = NL + NL1 ELSE CALL MESSAGE('UNABLE TO ADD HOLE LINES TO REGION LINE LIST') ERR = .TRUE. GO TO 380 END IF C TACK THE HOLE LINE LIST ONTO THE BOUNDARY LINE LIST IF (NPERIM(NPRM) .NE. NH) THEN CALL MESSAGE('INTERVAL MISMATCH ON HOLE PERIMETER') ERR = .TRUE. GO TO 380 END IF ISTART = 0 DIST = 0.0 DO 340 I = 1, NH SUM = 0.0 I1 = I - 1 DO 330 J = 1, NH I1 = I1 + 1 IF (I1 .GT. NH) I1 = 1 I2 = NXH(I1) SUM = SUM + (XN(I2) - X(J))**2 + (YN(I2) - Y(J))**2 330 CONTINUE IF (SUM .LT. DIST .OR. ISTART .EQ. 0) THEN DIST = SUM ISTART = I END IF 340 CONTINUE NNNX = NNN DO 350 J = 1, NH NNN = NNN + 1 XN(NNN) = X(J) YN(NNN) = Y(J) NUID(NNN) = NID(J, NPRM) 350 CONTINUE C FIRST ROW OF ELEMENTS CALL INNERH (MXND, NXH, NUID, LXK, KXL, NXL, LXN, KKK, LLL, & NNN, NNNX, NH, ISTART, IAVAIL, NAVAIL, NOROOM, ERR) IF (NOROOM .OR. ERR) GO TO 380 C INSERT INNER NECKLACE OF ELEMENTS ISTART = 1 DO 370 J = 1, INSIDE NNNX = NNN DO 360 I = 1, NH NNN = NNN + 1 NXH(I) = NNNX - NH + I XN(NNN) = XN(NXH(I)) YN(NNN) = YN(NXH(I)) NUID(NNN) = NUID(NXH(I)) NUID(NXH(I)) = 0 LXN(2, NXH(I)) = ABS(LXN(2, NXH(I))) 360 CONTINUE CALL INNERH (MXND, NXH, NUID, LXK, KXL, NXL, LXN, KKK, LLL, & NNN, NNNX, NH, ISTART, IAVAIL, NAVAIL, NOROOM, ERR) IF (NOROOM .OR. ERR) GO TO 380 370 CONTINUE END IF 380 CONTINUE RETURN END