PROGRAM WAVECOMP
C======================================================================
C                COMPUTATION OF WAVE HEIGHT COEFFICIENT 
C        AT SELECTED POINTS IN INTERIOR OF COMPUTATIONAL DOMAIN
C
C  NOTE: TOPOGRAPHY FUNCTION OF WAVE PROPERGATION MUST BE EVALUATED
C        BY HLM8LINQ.FOR PRIOR TO THIS PROGRAM EXCECUTION
C
C                 ELEMENT TYPE FOR BOUNDARY: LINEAR ELEMENT
C                 ELEMENT TYPE FOR DOMAIN: FOUR-NODED ELEMENT
C                 INPUT FILES: BEM1.DAT & BOUNDARY.BIN
C              PROGRAMMED BY EIJI FUKUMORI // 2025 JAN. 12
C======================================================================
      IMPLICIT REAL*8 ( A-H , O-Z )
      PARAMETER (MXE=150, MXN=MXE,INTEPT=6, ND=2 )
      PARAMETER ( MXEI=50000, MXNI=50000,NDI=4 )
      DIMENSION XE(ND),YE(ND),SAI(INTEPT),W(INTEPT),NODEX(MXE,ND),
     *  X(MXN),Y(MXN),WAVEHB(MXN)
      DIMENSION XI(MXNI),YI(MXNI), NODEXI(MXEI,NDI),WAVEH(MXNI)
      COMPLEX*16 BV(MXE,ND),GE(ND),FE(ND),H(MXN),C2
      COMPLEX*16 HI(MXNI)
C========================= INITIAL SET-UPS ============================
C
      PI = 4.D0 * DATAN( 1.D0)
      C2 = 1.D0/ DCMPLX(0.,4.D0)
      CALL GRULE ( INTEPT, SAI, W )
C========================= READING IN DATA ============================
C
      CALL INPUT (OMEGA,ND,MXE,MXN,NE,NNODE,NODEX,BV,X,Y,H,WAVEHB)
C      ...TYPE(I)=1 ---> TEMPERATURE PRESCRIBED
C      ...TYPE(I)=2 ---> HEAT FLUX PRESCRIBED
C=============== EVALUATION OF ELEMENT SIZE AND OBJECT SIZES ==========
      CALL SIZES (ND,MXE,MXN,NE,NNODE,NODEX,X,Y,DS,
     *     BODYX,BODYY,CENTERX, CENTERY )
C====== NODAL POINTS AND ELEMENTS CREATION FOR INTERIOR POINTS=========
      CALL CREATE ( NDI,MXEI,MXNI,DS,BODYX,BODYY,CENTERX,CENTERY,
     * NEI, NNODEI, NODEXI,XI,YI )
C================== INTERNAL POINTS   =================================
C
      CALL DOMAIN ( PI,OMEGA,INTEPT,ND,MXE,MXN,MXNI,C2,NNODEI,
     *       NE,  GE,FE, SAI,W,XI,YI,NODEX,X,Y,H,BV,HI )
C============== COMPUTATION OF WAVE HEIGHT COEFFICIENT ================
      CALL WAVEHT ( OMEGA, MXNI,NNODEI,HI, XI, WAVEH  )
C========== MERGING BOUNDARY WAVE HEIGHT TO DOMAIN WAVE HEIGHT ========
      CALL MERGE ( MXN,NNODE,X,Y,WAVEHB,MXNI,NNODEI,XI,YI,WAVEH )
C==================== CREATE FEM LIKE INPUT FILE ======================
      CALL CRFILE ( NDI,MXEI,MXNI,NEI, NNODEI, NODEXI,XI,YI,WAVEH )
      STOP 'NORMAL TERMINATION'
      END
C
C
      SUBROUTINE MERGE ( MXN,NNODE,X,Y,WAVEHB,MXNI,NNODEI,XI,YI,WAVEH )
      IMPLICIT REAL*8 ( A-H , O-Z )
      DIMENSION XI(MXNI),YI(MXNI),WAVEH(MXNI)
      DIMENSION X(MXN),Y(MXN),WAVEHB(MXN)
      DO I = 1 , NNODE
      RMIN = DSQRT ( (XI(1)-X(I))**2 + (YI(1)-Y(I))**2 )
      LOC = 1
      DO J = 2 , NNODEI
      R = DSQRT ( (XI(J)-X(I))**2 + (YI(J)-Y(I))**2 )
      IF ( R .LT. RMIN ) THEN
      LOC = J
      RMIN = R
      END IF
      END DO
      WAVEH(LOC) = WAVEHB(I)
      XI(LOC) = X(I)
      YI(LOC) = Y(I)
      END DO
      RETURN
      END
C
C
      SUBROUTINE CRFILE ( NDI,MXEI,MXNI,NEI,NNODEI,NODEXI,XI,YI,WAVEH )
      IMPLICIT REAL*8 ( A-H , O-Z )
      DIMENSION NODEXI(MXEI,NDI), XI(MXNI),YI(MXNI),WAVEH(MXNI)
      OPEN (1,FILE='DOMAIN.BIN',STATUS='UNKNOWN',FORM='UNFORMATTED')
      WRITE(1) NEI
      WRITE(1) NNODEI
      DO I = 1 , NEI
      WRITE(1) (NODEXI(I,J),J=1,NDI)
      END DO
      WRITE(1) ( XI(I) , I=1 , NNODEI )
      WRITE(1) ( YI(I) , I=1 , NNODEI )
      WRITE(1) ( WAVEH(I) , I=1 , NNODEI )
      CLOSE (1)
      RETURN
      END
C
C
      SUBROUTINE CREATE ( NDI,MXEI,MXNI,DS,BODYX,BODYY,CENTERX,CENTERY,
     * NEI, NNODEI, NODEXI,XI,YI )
      IMPLICIT REAL*8 ( A-H , O-Z )
      DIMENSION NODEXI(MXEI,NDI), XI(MXNI),YI(MXNI)
C------ IOFFXUP = SEE HOMEPAGE FOR EXPLANATION
C------ IOFFXDW = SEE HOMEPAGE FOR EXPLANATION
C------ IOFFY   = SEE HOMEPAGE FOR EXPLANATION
      DX = DS
      DY = DS
      IOFFXUP = 1
      IOFFXDW = 1
      IOFFY = 1
      TLX  = (IOFFXUP+1+IOFFXDW)*BODYX
      TLY  = (IOFFY  +1+IOFFY  )*BODYY
      NEX = TLX/DS
      NEY = TLY/DS
      NEY = NEY/2*2
      XORIGN = CENTERX - BODYX/2. - IOFFXUP*BODYX
      YORIGN = CENTERY - (NEY/2)*DS
      NDX = NEX + 1
      NDY = NEY + 1
C=======================================================================
      WRITE (*,*) 'DOMAIN LENGTH IN X (TLX) =',TLX
      WRITE (*,*) 'DOMAIN LENGTH IN Y (TLY) =',TLY
      WRITE (*,*) 'NUMBER OF ELEMENTS IN X (NEX) =', NEX
      WRITE (*,*) 'NUMBER OF ELEMENTS IN Y (NEY) =', NEY
      WRITE (*,*) 'INCREMENTAL LENGTH IN X (DX) =', DX
      WRITE (*,*) 'INCREMENTAL LENGTH IN Y (DX) =', DY
      WRITE (*,*) 'ORIGIN OF GLOBAL COORDINATES =',XORIGN,YORIGN
C=======================================================================
C                    ELEMENT CREATION
      NEI = 0
      DO J = 1 , NEX
      DO I = 1 , NEY
      NEI = NEI + 1
      IF ( NEI .GT. MXEI ) STOP 'NEI > MXEI'
      NODEXI(NEI,1) = NDY*(J-1) + I
      NODEXI(NEI,2) = NODEXI(NEI,1) + NDY
      NODEXI(NEI,3) = NODEXI(NEI,2) + 1
      NODEXI(NEI,4) = NODEXI(NEI,1) + 1
      END DO
      END DO
C=======================================================================
C                 NODAL COORDINATE CREATION
      NNODEI = 0
      DO I = 1 , NDX
      DO J = 1 , NDY
      NNODEI = NNODEI + 1
      IF ( NNODEI .GT. MXNI ) STOP 'NNODEI > MXNI'
      XI(NNODEI) = DX*(I-1) + XORIGN
      YI(NNODEI) = DY*(J-1) + YORIGN
      END DO
      END DO
      WRITE(*,*) 'NUMBER OF DOMAIN ELEMENTS =',NEI
      WRITE(*,*) 'NUMBER OF DOMAIN NODAL POINTS =',NNODEI
      RETURN
      END
C
C
      SUBROUTINE SIZES ( ND,MXE,MXN,NE,NNODE,NODEX,X,Y,DS,
     *     BODYX,BODYY,CENTERX, CENTERY )
      IMPLICIT REAL*8 ( A-H , O-Z )
      DIMENSION NODEX(MXE,ND), X(MXN),Y(MXN)
C
C------ BODYX = SIZE OF OBJECT IN X COORDINATE
C------ BODYY = SIZE OF OBJECT IN Y COORDINATE
C
C------ (CENTERX,CENTERY) = CENTER OF OBJECT
C
C------ AVERAGE ELEMENT LENGTH
      XMIN = X(1)
      XMAX = X(1)
      YMIN = Y(1)
      YMAX = Y(1)
      DO I = 2 , NNODE
      XMIN = DMIN1 ( XMIN, X(I) )
      XMAX = DMAX1 ( XMAX, X(I) )
      YMIN = DMIN1 ( YMIN, Y(I) )
      YMAX = DMAX1 ( YMAX, Y(I) )
      END DO
      BODYX = XMAX - XMIN
      BODYY = YMAX - YMIN
      CENTERX = ( XMAX + XMIN ) / 2.D0
      CENTERY = ( YMAX + YMIN ) / 2.D0
      DS = 0.D0
      DO I = 1 , NE
      DX = X(NODEX(I,2)) - X(NODEX(I,1))
      DY = Y(NODEX(I,2)) - Y(NODEX(I,1))
      DS = DS + DSQRT ( DX*DX + DY*DY )
      END DO
      DS = DS / DFLOAT(NE)
      RETURN
      END
C
C
      SUBROUTINE WAVEHT ( OMEGA, MXNI,NNODEI,HI, XI, WAVEH  )
      IMPLICIT REAL*8 ( A-H , O-Z )
      DIMENSION WAVEH(MXNI),XI(MXNI)
      COMPLEX*16 HI(MXNI)
      DO I = 1 , NNODEI
      REALPT = DREAL ( HI(I) ) + DCOS( OMEGA*XI(I) )
      FIMGPT = DIMAG ( HI(I) ) + DSIN( OMEGA*XI(I) )
      WAVEH(I) = DSQRT ( REALPT**2 + FIMGPT**2 )
      END DO
      RETURN
      END
C
C
      SUBROUTINE INPUT (OMEGA,ND,MXE,MXN,NE,NNODE,NODEX,BV,X,Y,H,WAVEHB)
      IMPLICIT REAL*8 ( A-H , O-Z )
      COMPLEX*16 BV(MXE,ND),H(MXN)
      DIMENSION X(MXE),Y(MXE),NODEX(MXE,ND),WAVEHB(MXN)
C=========>TAKING IN DATA FROM BEM1.DAT
      OPEN ( 1, FILE='BEM1.DAT', STATUS='OLD' )
      READ (1,*) OMEGA
      READ (1,*) NE
      DO IEL = 1 , NE
      READ (1,*) I,(NODEX(I,J),J=1,ND)
      END DO
      READ(1,*) NNODE
      DO I = 1 , NNODE
      READ (1,*) NODE, X(NODE), Y(NODE)
      END DO
      CLOSE (1)
C=========> WAVEHEIGHT ON BOUNDARY NODES
      OPEN ( 1, FILE='WHCOEFFI.CNT', STATUS='OLD' )
      DO I = 1 , NNODE
      READ (1,*) DUMMY, WAVEHB(I)
      END DO
      CLOSE (1)
C=========> TAKING IN BOUNDARY VALUES COMPUTED FROM ((HLM8LINQ.FOR))
      OPEN (1,FILE='BOUNDARY.BIN',STATUS='UNKNOWN',FORM='UNFORMATTED')
      DO I = 1 , NE
      READ(1) BV(I,1), BV(I,2)
      END DO
      DO I = 1 , NNODE
      READ(1) H(I)
      END DO      
      CLOSE (1)
      RETURN
      END
C
C
      SUBROUTINE INTE (PI,OMEGA,INTEPT,ND,XP,YP,C2,XE,YE,SAI,W,GE,FE)
      IMPLICIT REAL*8 ( A-H , O-Z )
      DIMENSION XE(ND),YE(ND), SAI(INTEPT),W(INTEPT)
      COMPLEX*16 GE(ND),FE(ND),C2, H0, H1
      DO I = 1 , ND
      GE(I) = DCMPLX(0.D0,0.D0)
      FE(I) = DCMPLX(0.D0,0.D0)
      END DO
      DX = XE(2) - XE(1)
      DY = YE(2) - YE(1)
      DS = DSQRT ( DX*DX + DY*DY )
      DETJ = DS/2.D0
      XM = ( XE(2) + XE(1) ) /2.D0
      YM = ( YE(2) + YE(1) ) /2.D0
C--------GAUSS INTEGRATION
      DO IGAUSS = 1 , INTEPT
      XGAUSS = DX/2.D0*SAI(IGAUSS) + XM
      YGAUSS = DY/2.D0*SAI(IGAUSS) + YM
      RX = XGAUSS - XP
      RY = YGAUSS - YP
      R = DSQRT ( RX*RX + RY*RY )
C------- COMPUTATION OF SHAPE FUNCTIONS
      SF1 = 0.5D0 * ( 1.D0 - SAI(IGAUSS) )
      SF2 = 0.5D0 * ( 1.D0 + SAI(IGAUSS) )
C-------- COMPUTATION OF BESSEL FUNCTIONS --------
      Z = R * OMEGA
      CALL BESSEL ( PI, Z , H0, H1 )
C-------- INTEGRATION OF G(R)
      GE(1) = GE(1) + H0 * W(IGAUSS) * SF1
      GE(2) = GE(2) + H0 * W(IGAUSS) * SF2
C-------- INTEGRATION OF F(R)
      RDOTN = (RX*DY-RY*DX) / DS
      DRDN = RDOTN / R
      FE(1) = FE(1) + OMEGA*H1 * DRDN * W(IGAUSS) * SF1
      FE(2) = FE(2) + OMEGA*H1 * DRDN * W(IGAUSS) * SF2
      END DO
      GE(1) =  C2 * DETJ * GE(1)
      GE(2) =  C2 * DETJ * GE(2)
      FE(1) = -C2 * DETJ * FE(1)
      FE(2) = -C2 * DETJ * FE(2)
      RETURN
      END
C
C
      SUBROUTINE DOMAIN ( PI,OMEGA,INTEPT,ND,MXE,MXN,MXNI,C2,NNODEI,
     *       NE,  GE,FE, SAI,W,XI,YI,NODEX,X,Y,H,BV,HI )
      IMPLICIT REAL*8 ( A-H , O-Z )
      DIMENSION NODEX(MXE,ND), SAI(INTEPT), W(INTEPT),
     *  X(MXN),Y(MXN),XE(ND),YE(ND)
      DIMENSION XI(MXNI),YI(MXNI)
      COMPLEX*16 GE(ND),FE(ND), BV(MXE,ND),H(MXN), SUM
      COMPLEX*16  HI(MXNI), C2
C
      WRITE(*,*) 'THIS PROCESS REQUIRES A LOT OF CPU TIME.'
      C1 = - 1.D0/ ( 8.D0* DATAN( 1.D0) )
      DO INSIDE = 1 , NNODEI
      IF(INSIDE-INSIDE/100*100 .EQ. 0 ) THEN
      IPERCENT= 100.- FLOAT(INSIDE)/FLOAT(NNODEI)*100.
      WRITE(*,*)'REMAINING CALCULATION TIME = ',IPERCENT, '%'
      END IF
      XP = XI(INSIDE)
      YP = YI(INSIDE)
      SUM = DCMPLX(0.D0,0.D0)
      C=1.D0
      DO IEL = 1 , NE
        DO I = 1 , ND
         XE(I) = X( NODEX(IEL,I) )
         YE(I) = Y( NODEX(IEL,I) )
        END DO
        CALL INTELPS ( INTEPT,ND,XP,YP,C1,XE,YE,SAI,W, FE1,FE2 )
         C = C + FE1 + FE2
      END DO
      IF ( C .GT. 0.9D0 ) THEN
      DO IEL = 1 , NE
        DO I = 1 , ND
         XE(I) = X( NODEX(IEL,I) )
         YE(I) = Y( NODEX(IEL,I) )
        END DO
        CALL INTE ( PI,OMEGA,INTEPT,ND,XP,YP,C2,XE,YE,SAI,W,GE,FE )
        DO J = 1 , ND
         SUM = SUM + FE(J)*H(NODEX(IEL,J)) - GE(J)*BV(IEL,J) 
        END DO
      END DO
      END IF
      HI(INSIDE) = SUM/C
      END DO
      RETURN
      END
C
C
      SUBROUTINE GRULE ( N , SAI , W )
      IMPLICIT REAL*8 ( A-H , O-Z )
      DIMENSION SAI(N) , W(N)
      IF ( N .LT. 2 ) STOP'N<2'
      IF ( N .GT. 6 ) STOP'N>6'
      IF ( N .EQ. 2 ) THEN
      SAI(1) = DSQRT(3.D0)/3.D0
      W(1) = 1.D0
      SAI(2) = - SAI(1)
      W(2) = W(1)
      RETURN
      END IF
      IF ( N .EQ. 3 ) THEN
      SAI(1) = DSQRT(15.D0)/5.D0
      SAI(2) = 0.D0
      W(1) = 5.D0/ 9.D0
      W(2) = 8.D0/ 9.D0
      SAI(3) = - SAI(1)
      W(3) = W(1)
      RETURN
      END IF
      IF ( N .EQ. 4 ) THEN
      SAI(1) = 0.33998104358485D0
      SAI(2) = 0.86113631159405D0
        W(1) = 0.65214515486254D0
        W(2) = 0.34785484513745D0
      SAI(3) = -SAI(2)
      SAI(4) = -SAI(1)
      W(3) = W(2)
      W(4) = W(1)
      RETURN
      END IF
      IF ( N .EQ. 5 ) THEN
      SAI(1) = 0.90617984593866D0
      SAI(2) = 0.53846931010568D0
      SAI(3) = 0.D0
        W(1) = 0.23692688505619D0
        W(2) = 0.47862867049937D0
        W(3) = 5.12D0 / 9.D0
      SAI(4) = -SAI(2)
      SAI(5) = -SAI(1)
      W(4) = W(2)
      W(5) = W(1)
      RETURN
      END IF
      IF ( N .EQ. 6 ) THEN
      SAI(1) = 0.23861918608320D0
      SAI(2) = 0.66120938646626D0
      SAI(3) = 0.93246951420315D0
        W(1) = 0.46791393457269D0
        W(2) = 0.36076157304814D0
        W(3) = 0.17132449237917D0
      SAI(4) = -SAI(1)
      SAI(5) = -SAI(2)
      SAI(6) = -SAI(3)
        W(4) = W(1)
        W(5) = W(2)
        W(6) = W(3)
      END IF
      RETURN
      END
C
C
      SUBROUTINE BESSEL ( PI, X , H0, H1 )
      IMPLICIT REAL*8 ( A-H , O-Z )
      COMPLEX*16 H0, H1
      PARAMETER ( EULER = 0.5772156649015D0, ALLOWANC=1.D-16 )
C--------- BJ0, BJ1
      X22 = (X/2.D0) **2
      PRODUCT = 1.D0
      SIGNCH = 1.D0
      FACT = 1.D0
      SUM0 = 0.D0
      SUM1 = 0.D0
      M = 1
      CHECK = 1.D0
      DO WHILE ( DABS(CHECK) .GT. ALLOWANC )
      FACT = FACT * DFLOAT(M)
      PRODUCT = PRODUCT * X22
      SIGNCH = -SIGNCH
      DELTA0 = SIGNCH*PRODUCT/(FACT*FACT)
      SUM0 = SUM0 + DELTA0
      IF ( SUM0 .EQ. 0.D0 ) THEN
      CHECK = DELTA0
      ELSE
      CHECK = DELTA0 / SUM0
      END IF
      SUM1 = SUM1 + SIGNCH*PRODUCT/(FACT*FACT*DFLOAT(M+1))
      M = M + 1
      IF ( M .GT. 1000 ) STOP
      END DO
      BJ0 = 1.D0 + SUM0
      BJ1 = (X/2.D0) * ( 1.D0 + SUM1 )
C
C-------- BN0, BN1
      PRODUCT = 1.D0
      SIGNCH = 1.D0
      FACT = 1.D0
      SUM0 = 0.D0
      SUM1 = 0.D0
      M = 1
      CHECK = 1.D0
      DO WHILE ( DABS(CHECK) .GT. ALLOWANC )
      FACT = FACT * DFLOAT(M)
      PRODUCT = PRODUCT * X22
      SIGNCH = -SIGNCH
C..............SUM OF 1/1+1/2+1/3+.......+1/M
      SUMM = 0.D0
      DO I = 1 , M
      SUMM = SUMM + 1.D0 / DFLOAT(I)
      END DO
      DELTA0 = SIGNCH*PRODUCT/(FACT*FACT) * 2.D0*SUMM
      SUM0 = SUM0 + DELTA0
      IF ( SUM0 .EQ. 0.D0 ) THEN
      CHECK = DELTA0
      ELSE
      CHECK = DELTA0 / SUM0
      END IF
      SUM1 = SUM1 + SIGNCH*PRODUCT/(FACT*FACT*DFLOAT(M+1)) *
     *              (2.D0*SUMM+1.D0/DFLOAT(M+1))
      M = M + 1
      IF ( M .GT. 1000 ) STOP
      END DO
      BN0 = (2.D0/PI)*BJ0*(EULER+DLOG(X/2.D0)) - 1.D0/PI*SUM0
      BN1 = (2.D0/PI)*BJ1*(EULER+DLOG(X/2.D0)) - X/(2.D0*PI) -
     *      1.D0/PI*(X/2.D0)*SUM1 - 2.D0/(PI*X)
C----------- ASSEMBLE THEM INTO COMPLEX NUMBERS
      H0 = DCMPLX(BJ0,BN0)
      H1 = DCMPLX(BJ1,BN1)
      RETURN
      END
C
C
      SUBROUTINE INTELPS (INTEPT,ND,XP,YP,C1, XE, YE, SAI,W,FE1,FE2 )
      IMPLICIT REAL*8 ( A-H , O-Z )
      DIMENSION XE(ND),YE(ND), SAI(INTEPT),W(INTEPT)
      FE1 = 0.D0
      FE2 = 0.D0
      DX = XE(2) - XE(1)
      DY = YE(2) - YE(1)
      DS = DSQRT ( DX*DX + DY*DY )
      DETJ = DS/2.D0
      XM = ( XE(2) + XE(1) ) /2.D0
      YM = ( YE(2) + YE(1) ) /2.D0
C--------GAUSS INTEGRATION
      DO IGAUSS = 1 , INTEPT
      XGAUSS = DX/2.D0*SAI(IGAUSS) + XM
      YGAUSS = DY/2.D0*SAI(IGAUSS) + YM
      RX = XGAUSS - XP
      RY = YGAUSS - YP
      R = DSQRT ( RX*RX + RY*RY )
      SF1 = 0.5D0 * ( 1.D0 - SAI(IGAUSS) )
      SF2 = 0.5D0 * ( 1.D0 + SAI(IGAUSS) )
C-------- INTEGRATION OF F(R)
      TEMP = (RX*DY-RY*DX) / (R*R) * W(IGAUSS)
      FE1 = FE1 + TEMP * SF1
      FE2 = FE2 + TEMP * SF2
      END DO
      FE1 = -C1 * DETJ /DS * FE1
      FE2 = -C1 * DETJ /DS * FE2
      RETURN
      END