XBeach
C:/repositories/XBeach/trunk/src/xbeachlibrary/interp.F90
Go to the documentation of this file.
00001 module interp
00002    implicit none
00003    private
00004    public linear_interp, interp_in_cyclic_function, interp_using_trapez_rule
00005    public grmap2, mkmap, grmap, linear_interp_2d, make_map, mkmap_step, trapezoidal
00006    save
00007 contains
00008    pure subroutine linear_interp_2d(X,nx,Y,ny,Z,xx,yy,zz,method,exception)
00009 
00010       implicit none
00011       ! input/output
00012       integer,intent(in)                    :: nx,ny
00013       real*8,dimension(nx),intent(in)       :: X
00014       real*8,dimension(ny),intent(in)       :: Y
00015       real*8,dimension(nx,ny),intent(in)    :: Z
00016       real*8,intent(in)                     :: xx,yy
00017       real*8,intent(out)                    :: zz
00018       character(len=*),intent(in)           :: method
00019       real*8,intent(in)                     :: exception
00020       ! internal
00021       integer,dimension(4)                  :: ind
00022       real*8,dimension(2)                   :: yint
00023       real*8                                :: modx,mody,disx,disy
00024       logical                               :: interpX,interpY
00025 
00026       ! does the interpolation point fall within the data?
00027       if (xx>=minval(X) .and. xx<=maxval(X)) then
00028          interpX = .true.
00029       else
00030          interpX = .false.
00031       endif
00032       if (yy>=minval(Y) .and. yy<=maxval(Y)) then
00033          interpY = .true.
00034       else
00035          interpY = .false.
00036       endif
00037 
00038       if (interpX .and. interpY) then
00039          ! find rank position xx in X direction
00040          ind(1) = minloc(X,1,X>=xx)
00041          ind(2) = maxloc(X,1,X<=xx)
00042          ! find rank position yy in Y direction
00043          ind(3) = minloc(Y,1,Y>=yy)
00044          ind(4) = maxloc(Y,1,Y<=yy)
00045          ! distance between X points and Y points
00046          disx = X(ind(1))-X(ind(2))
00047          disy = Y(ind(3))-Y(ind(4))
00048          ! relative position of (xx,yy) on disx,disy
00049          if (disx>0.d0) then
00050             modx = (xx-X(ind(2)))/disx
00051          else
00052             modx = 0.d0   ! xx corresponds exactly to X point
00053          endif
00054          if (disy>0.d0) then
00055             mody = (yy-Y(ind(4)))/disy
00056          else
00057             mody = 0.d0   ! yy corresponds exactly to Y point
00058          endif
00059          ! interpolate the correct Y value, based on two nearest X intersects
00060          ! if disy==0 then only single interpolation needed. This could also be done for X,
00061          ! but since this is used by waveparams and the interp angles (Y) are more often equal
00062          ! this is probably faster.
00063          if (disy>0.d0) then
00064             yint(1) = (1.d0-modx)*Z(ind(2),ind(3))+modx*Z(ind(1),ind(3))
00065             yint(2) = (1.d0-modx)*Z(ind(2),ind(4))+modx*Z(ind(1),ind(4))
00066             zz = (1.d0-mody)*yint(2)+mody*yint(1)
00067          else
00068             zz = (1.d0-modx)*Z(ind(2),ind(3))+modx*Z(ind(1),ind(3))
00069          endif
00070       else
00071          select case (method)
00072           case ('interp')
00073             zz = exception
00074           case ('extendclosest')
00075             ! find closest X point
00076             ind(1) = minloc(abs(X-xx),1)
00077             ! find closest Y point
00078             ind(3) = minloc(abs(Y-yy),1)
00079             ! external value given that of closest point
00080             zz = Z(ind(1),ind(3))
00081           case default
00082             zz = exception
00083          endselect
00084       endif
00085 
00086    end subroutine linear_interp_2d
00087 
00088    !
00089    ! NAME
00090    !    linear_interp
00091    ! SYNOPSIS
00092    !    Interpolate linearly into an array Y given the value of X.
00093    !    Return both the interpolated value and the position in the
00094    !    array.
00095    !
00096    ! ARGUMENTS
00097    !    - X: independent array (sorted in ascending order)
00098    !    - Y: array whose values are a function of X
00099    !    - XX: specified value, interpolating in first array
00100    !    - YY: interpolation result
00101    !    - INDINT: (optional) index in array (x(indint) <= xx <= x(indint+1))
00102    !
00103    ! SOURCE
00104    !
00105    pure subroutine linear_interp(x, y, n, xx, yy, indint)
00106       integer,              intent(in) :: n
00107       real*8, dimension(n), intent(in) :: x
00108       real*8, dimension(n), intent(in) :: y
00109       real*8, intent(in)               :: xx
00110       real*8, intent(out)              :: yy
00111       integer, intent(out), optional   :: indint
00112       !****
00113       !
00114       ! CODE: linear interpolation
00115       !
00116       !
00117       !
00118       real*8           :: a,  b, dyy
00119       integer          :: j
00120 
00121       yy = 0.0d0
00122       if ( present(indint) ) then
00123          indint = 0
00124       endif
00125 
00126       if (n.le.0) return
00127       !
00128       ! *** N GREATER THAN 0
00129       !
00130       if (n.eq.1) then
00131          yy = y(1)
00132          return
00133       endif
00134 
00135       call binary_search( x, n, xx, j )
00136 
00137       if ( j .le. 0 ) then
00138          yy = y(1)
00139       elseif ( j .ge. n ) then
00140          yy = y(n)
00141       else
00142          a = x (j+1)
00143          b = x (j)
00144          if ( a .eq. b ) then
00145             dyy = 0.0d0
00146          else
00147             dyy = (y(j+1) - y(j)) / (a - b)
00148          endif
00149          yy = y(j) + (xx - x(j)) * dyy
00150       endif
00151 
00152       if ( present(indint) ) then
00153          indint = j
00154       endif
00155 
00156       return
00157 
00158    end subroutine linear_interp
00159 
00160    !****f* Interpolation/binary_search
00161    !
00162    ! NAME
00163    !    binary_search
00164    ! SYNOPSIS
00165    !    Perform a binary search in an ordered real array
00166    !    to find the largest entry equal or lower than a given value:
00167    !    Given an array XX of length N, given value X, return a value J
00168    !    such that X is between XX(J) en XX (J+1)
00169    !
00170    !    XX must be monotonic, either decreasing or increasing
00171    !    J=0 or J=N indicates X is out of range.
00172    !
00173    ! ARGUMENTS
00174    !    - XX: ordered array of values
00175    !    - X: value to be found
00176    !    - J: index such that X is between XX(J) and XX(J+1)
00177    !
00178    ! SOURCE
00179    !
00180    pure subroutine binary_search(xx, n, x, j)
00181       integer,              intent(in) :: N
00182       real*8, dimension(N), intent(in) :: xx
00183       real*8, intent(in)               :: x
00184       integer, intent(out)             :: j
00185       !****
00186       !
00187       ! CODE: binary search in (real) arrays
00188       !
00189       ! Requirement:
00190       !    Parameter wp set to the proper kind
00191       !
00192       ! Subroutine from 'Numerical recipes' Fortran  edition.
00193       ! Given an array XX of length N, given value X, return a value J
00194       ! such that X is between XX(J) en XX (J+1)
00195       ! XX must be monotonic, either decreasing or increasin
00196       ! J=0 or J=N indicates X is out of range.
00197 
00198 
00199       !
00200       ! Local variables
00201       !
00202       integer   jl, ju, jm
00203       logical   l1, l2
00204 
00205       jl = 0
00206       ju = n+1
00207 10    if (ju-jl .gt. 1) then
00208          jm = (ju+jl)/2
00209          l1 = xx(n) .gt. xx(1)
00210          l2 = x .gt. xx(jm)
00211          if ( (l1.and.l2) .or. (.not. (l1 .or. l2)) ) then
00212             jl = jm
00213          else
00214             ju = jm
00215          endif
00216          goto 10
00217       endif
00218 
00219       j = jl
00220 
00221       return
00222 
00223    end subroutine binary_search
00224 
00225    subroutine mkmap(code      ,x1        ,y1        ,m1        ,n1        , &
00226    & x2        ,y2        ,n2        ,xs        ,ys        , &
00227    & nrx       ,nry       ,iflag     ,nrin      ,w         , &
00228    & iref      ,iprint    ,covered   ,xymiss)
00229       !!--description-----------------------------------------------------------------
00230       !
00231       !
00232       !     SUBROUTINE MKMAP
00233       !     Interpolation of curvilinear, numerically ordered grid (grid1)
00234       !     to random points, with weighting points (grid2).
00235       !
00236       !     J.A. Roelvink
00237       !     Deltares
00238       !     24-2-1992 (MKMAP
00239       !
00240       !     Given: numerically ordered grid M1*N1
00241       !     with coordinates X1 (1:M1,1:N1)
00242       !                  and Y1 (1:M1,1:N1)
00243       !
00244       !     Also given: random points X2(1:N2)
00245       !                           and Y2(1:N2)
00246       !
00247       !     To be determined:  weighting factors and pointers for bilinear interpolation
00248       !     Weighting factors and locations of the requested (random) points in the
00249       !     ordered grid are saved in resp.
00250       !     W(1:4,1:N2) and Iref(1:4,1:N2)
00251       !
00252       !!--pseudo code and references--------------------------------------------------
00253       ! NONE
00254       !!--declarations----------------------------------------------------------------
00255       !
00256       implicit none
00257       !
00258       ! Global variables
00259       !
00260       integer                    , intent(in)  :: iprint
00261       integer                    , intent(in)  :: m1
00262       integer                    , intent(in)  :: n1
00263       integer                                  :: n2
00264       integer , dimension(4 , n2), intent(out) :: iref
00265       integer , dimension(m1, n1), intent(in)  :: code
00266       integer , dimension(n2)                  :: covered !  0: target point is not covered by source grid (default)
00267       !  1: target point is covered by   valid points of source grid
00268       ! -1: target point is covered by invalid points of source grid
00269       integer , dimension(n2)                  :: iflag
00270       integer , dimension(n2)                  :: nrin
00271       integer , dimension(n2)                  :: nrx
00272       integer , dimension(n2)                  :: nry
00273       real                       , intent(in)  :: xymiss  ! missing value in grid 1
00274       real*8  , dimension(4 , n2)              :: w       ! Remains single precision!
00275       real*8  , dimension(m1, n1), intent(in)  :: x1
00276       real*8  , dimension(m1, n1), intent(in)  :: y1
00277       real*8  , dimension(n2)                  :: x2
00278       real*8  , dimension(n2)                  :: xs
00279       real*8  , dimension(n2)                  :: y2
00280       real*8  , dimension(n2)                  :: ys
00281       !
00282       ! Local variables
00283       !
00284       integer                           :: i
00285       integer                           :: i1
00286       integer                           :: i2
00287       integer                           :: ier
00288       integer                           :: iin
00289       integer                           :: inout
00290       integer                           :: ip
00291       integer                           :: j1
00292       integer                           :: lomaxx
00293       integer                           :: lominx
00294       integer                           :: lomnx
00295       integer                           :: lomny
00296       integer                           :: m1max
00297       integer                           :: m1min
00298       integer                           :: n1max
00299       integer                           :: n1min
00300       integer                           :: nin
00301       real*8                           :: eps
00302       real*8                            :: xpmax
00303       real*8                            :: xpmean
00304       real*8                            :: xpmin
00305       real*8                            :: ypmax
00306       real*8                            :: ypmean
00307       real*8                            :: ypmin
00308       real*8  , dimension(5)            :: xp
00309       real*8  , dimension(5)            :: yp
00310       real*8  , dimension(4)            :: hbuff
00311       !
00312       !! executable statements -------------------------------------------------------
00313       !
00314       eps = 0.00001
00315       !
00316       !     Initialise tables
00317       !
00318       if (iprint==1) write (*, *) 'in mkmap', m1, n1, n2
00319       lomnx = 1
00320       lomny = 1
00321       m1min = 1
00322       m1max = m1
00323       n1min = 1
00324       n1max = n1
00325       nrx=0
00326       nry=0
00327       iflag=0
00328       nrin=0
00329       xs=0.d0
00330       ys=0.d0
00331       iref=0
00332       w=0.d0
00333       !
00334       ! Sort X2 en Y2
00335       !
00336       call sort(n2        ,x2        ,xs        ,nrx       )
00337       call sort(n2        ,y2        ,ys        ,nry       )
00338       !
00339       ! Loop over all cels of grid1
00340       !
00341       !
00342       do j1 = n1min, n1max - 1
00343          do i1 = m1min, m1max - 1
00344             !
00345             ! Cell definition
00346             !
00347             xp(1) = x1(i1, j1)
00348             xp(2) = x1(i1 + 1, j1)
00349             xp(3) = x1(i1 + 1, j1 + 1)
00350             xp(4) = x1(i1, j1 + 1)
00351             yp(1) = y1(i1, j1)
00352             yp(2) = y1(i1 + 1, j1)
00353             yp(3) = y1(i1 + 1, j1 + 1)
00354             yp(4) = y1(i1, j1 + 1)
00355             if (     (xp(1) > xymiss-eps .and. xp(1) < xymiss+eps) &
00356             & .or. (xp(2) > xymiss-eps .and. xp(2) < xymiss+eps) &
00357             & .or. (xp(3) > xymiss-eps .and. xp(3) < xymiss+eps) &
00358             & .or. (xp(4) > xymiss-eps .and. xp(4) < xymiss+eps) &
00359             & .or. (yp(1) > xymiss-eps .and. yp(1) < xymiss+eps) &
00360             & .or. (yp(2) > xymiss-eps .and. yp(2) < xymiss+eps) &
00361             & .or. (yp(3) > xymiss-eps .and. yp(3) < xymiss+eps) &
00362             & .or. (yp(4) > xymiss-eps .and. yp(4) < xymiss+eps) ) cycle
00363             !
00364             ! Determine minimum and maximum X and Y of the cell
00365             !
00366             xpmin =  1.e10
00367             xpmax = -1.e10
00368             ypmin =  1.e10
00369             ypmax = -1.e10
00370             do ip = 1, 4
00371                xpmin = min(xp(ip), xpmin)
00372                xpmax = max(xp(ip), xpmax)
00373                ypmin = min(yp(ip), ypmin)
00374                ypmax = max(yp(ip), ypmax)
00375             enddo
00376             xpmean = .5*(xpmin + xpmax)
00377             ypmean = .5*(ypmin + ypmax)
00378             !
00379             ! First selection of points of grid2 that can be located in the cell
00380             !
00381             ! Find centre of the cell in tables Xs and Ys
00382             !
00383             call hunt(xs        ,n2        ,xpmean    ,lomnx     )
00384             call hunt(ys        ,n2        ,ypmean    ,lomny     )
00385             !
00386             ! For points with X-values between Xpmin and Xpmax set: iFlag(i)=1
00387             !
00388             lominx = lomnx
00389             lomaxx = lomnx
00390             do i = lomnx, 1, -1
00391                if (xs(i)>=xpmin) then
00392                   lominx        = i
00393                   iflag(nrx(i)) = 1
00394                else
00395                   exit
00396                endif
00397             enddo
00398             do i = lomnx + 1, n2
00399                if (xs(i)<=xpmax) then
00400                   lomaxx        = i
00401                   iflag(nrx(i)) = 1
00402                else
00403                   exit
00404                endif
00405             enddo
00406             !
00407             ! For the points with Y-values between Ypmin and Ypmax,
00408             ! that also lie between Xpmin and Xpmax: Save them in NrIn
00409             !
00410             iin = 1
00411             do i = lomny, 1, -1
00412                if (ys(i)>=ypmin) then
00413                   nrin(iin) = nry(i)*iflag(nry(i))
00414                   iin       = iin + iflag(nry(i))
00415                else
00416                   exit
00417                endif
00418             enddo
00419             do i = lomny + 1, n2
00420                if (ys(i)<=ypmax) then
00421                   nrin(iin) = nry(i)*iflag(nry(i))
00422                   iin       = iin + iflag(nry(i))
00423                else
00424                   exit
00425                endif
00426             enddo
00427             nin = iin - 1
00428             !
00429             ! Put iFlag back to 0
00430             !
00431             do i = lominx, lomaxx
00432                if (i/=0) iflag(nrx(i)) = 0
00433             enddo
00434             !
00435             ! Check whether selected points of grid2 lie within the cell
00436             ! using subroutine IPON; if so, determine weights W of the surrounding
00437             ! values in grid1 using subroutine INTRP4. Save the weights in Wtab
00438             ! The reference to grid1 is saved in arrays Iref and Jref.
00439             !
00440             do iin = 1, nin
00441                i2 = nrin(iin)
00442                inout = -1
00443                call ipon(xp        ,yp        ,4         ,x2(i2)    , &
00444                &          y2(i2)    ,inout     )
00445                if (inout>=0) then
00446                   !
00447                   ! Check on point with nonsense information on source grid 1;
00448                   ! This depends on agreements
00449                   !
00450                   if (      (code(i1    , j1    )==1 .or. code(i1    , j1    )==3) &
00451                   & .and. (code(i1 + 1, j1    )==1 .or. code(i1 + 1, j1    )==3) &
00452                   & .and. (code(i1 + 1, j1 + 1)==1 .or. code(i1 + 1, j1 + 1)==3) &
00453                   & .and. (code(i1    , j1 + 1)==1 .or. code(i1    , j1 + 1)==3) ) then
00454                      !
00455                      ! grid2 point is covered by 4 valid grid1 points
00456                      !
00457                      covered(i2) = 1
00458                      call bilin5(xp, yp, x2(i2), y2(i2), hbuff, ier)
00459                      w(:, i2) = real(hbuff(:),4)
00460                      !
00461                      iref(1, i2) = i1 + (j1 - 1)*m1
00462                      iref(2, i2) = i1 + 1 + (j1 - 1)*m1
00463                      iref(3, i2) = i1 + 1 + j1*m1
00464                      iref(4, i2) = i1 + j1*m1
00465                   elseif (code(i1, j1)>0 .and. code(i1 + 1, j1)>0 .and. &
00466                   & code(i1 + 1, j1 + 1)>0 .and. code(i1, j1 + 1)>0) then
00467                      !
00468                      ! Grid2 point is covered by 4 valid grid1 points, containing
00469                      ! one or more boundary points:
00470                      ! - do not use grid1 values
00471                      ! - use extrapolation values
00472                      !
00473                      covered(i2) = 0
00474                   else
00475                      !
00476                      ! Grid2 point is not covered by 4 valid grid1 points:
00477                      ! - do not use grid1 values
00478                      ! - do not use extrapolation values
00479                      !
00480                      covered(i2) = -1
00481                   endif
00482                endif
00483             enddo
00484          enddo
00485       enddo
00486    end subroutine mkmap
00487 
00488    subroutine make_map(code, x1, y1, m1, n1, x2, y2, n2, w, iref, &
00489    &                   iprint    ,covered   ,xymiss)
00490       !!--description-----------------------------------------------------------------
00491       !
00492       !
00493       !     SUBROUTINE MKMAP
00494       !     Interpolation of curvilinear, numerically ordered grid (grid1)
00495       !     to random points, with weighting points (grid2).
00496       !
00497       !     J.A. Roelvink
00498       !     Deltares
00499       !     24-2-1992 (MKMAP
00500       !
00501       !     Given: numerically ordered grid M1*N1
00502       !     with coordinates X1 (1:M1,1:N1)
00503       !                  and Y1 (1:M1,1:N1)
00504       !
00505       !     Also given: random points X2(1:N2)
00506       !                           and Y2(1:N2)
00507       !
00508       !     To be determined:  weighting factors and pointers for bilinear interpolation
00509       !     Weighting factors and locations of the requested (random) points in the
00510       !     ordered grid are saved in resp.
00511       !     W(1:4,1:N2) and Iref(1:4,1:N2)
00512       !
00513       !!--pseudo code and references--------------------------------------------------
00514       ! NONE
00515       !!--declarations----------------------------------------------------------------
00516       !
00517       implicit none
00518       !
00519       ! Global variables
00520       !
00521       integer                    , intent(in)  :: iprint
00522       integer                    , intent(in)  :: m1
00523       integer                    , intent(in)  :: n1
00524       integer                    , intent(in)  :: n2
00525       integer , dimension(4 , n2), intent(out) :: iref
00526       real*8  , dimension(4 , n2), intent(out) :: w       ! Remains single precision!
00527       integer , dimension(m1, n1), intent(in)  :: code
00528       integer , dimension(n2)    , intent(out) :: covered !  0: target point is not covered by source grid (default)
00529       !  1: target point is covered by   valid points of source grid
00530       ! -1: target point is covered by invalid points of source grid
00531       real                       , intent(in)  :: xymiss  ! missing value in grid 1
00532       real*8  , dimension(m1, n1), intent(in)  :: x1
00533       real*8  , dimension(m1, n1), intent(in)  :: y1
00534       real*8  , dimension(n2), intent(in)      :: x2
00535       real*8  , dimension(n2), intent(in)      :: y2
00536       !
00537       ! Local variables
00538       !
00539       integer, dimension(:),allocatable             :: iflag
00540       integer, dimension(:),allocatable             :: nrin
00541       integer, dimension(:),allocatable             :: nrx
00542       integer, dimension(:),allocatable             :: nry
00543       real*8,  dimension(:),allocatable             :: xs
00544       real*8,  dimension(:),allocatable             :: ys
00545 
00546       integer                           :: i
00547       integer                           :: i1
00548       integer                           :: i2
00549       integer                           :: ier
00550       integer                           :: iin
00551       integer                           :: inout
00552       integer                           :: ip
00553       integer                           :: j1
00554       integer                           :: lomaxx
00555       integer                           :: lominx
00556       integer                           :: lomnx
00557       integer                           :: lomny
00558       integer                           :: m1max
00559       integer                           :: m1min
00560       integer                           :: n1max
00561       integer                           :: n1min
00562       integer                           :: nin
00563       real*8                           :: eps
00564       real*8                            :: xpmax
00565       real*8                            :: xpmean
00566       real*8                            :: xpmin
00567       real*8                            :: ypmax
00568       real*8                            :: ypmean
00569       real*8                            :: ypmin
00570       real*8  , dimension(5)            :: xp
00571       real*8  , dimension(5)            :: yp
00572       real*8  , dimension(4)            :: hbuff
00573       !
00574       allocate(iflag(n2))
00575       allocate(nrin(n2))
00576       allocate(nrx(n2))
00577       allocate(nry(n2))
00578       allocate(xs(n2))
00579       allocate(ys(n2))
00580       !! executable statements -------------------------------------------------------
00581       !
00582       eps = 0.00001
00583       !
00584       !     Initialise tables
00585       !
00586       if (iprint==1) write (*, *) 'in mkmap', m1, n1, n2
00587       lomnx = 1
00588       lomny = 1
00589       m1min = 1
00590       m1max = m1
00591       n1min = 1
00592       n1max = n1
00593       nrx=0
00594       nry=0
00595       iflag=0
00596       nrin=0
00597       xs=0.d0
00598       ys=0.d0
00599       iref=0
00600       w=0.d0
00601       !
00602       ! Sort X2 en Y2
00603       !
00604       call sort(n2        ,x2        ,xs        ,nrx       )
00605       call sort(n2        ,y2        ,ys        ,nry       )
00606       !
00607       ! Loop over all cels of grid1
00608       !
00609       !
00610       do j1 = n1min, n1max - 1
00611          do i1 = m1min, m1max - 1
00612             !
00613             ! Cell definition
00614             !
00615             xp(1) = x1(i1, j1)
00616             xp(2) = x1(i1 + 1, j1)
00617             xp(3) = x1(i1 + 1, j1 + 1)
00618             xp(4) = x1(i1, j1 + 1)
00619             yp(1) = y1(i1, j1)
00620             yp(2) = y1(i1 + 1, j1)
00621             yp(3) = y1(i1 + 1, j1 + 1)
00622             yp(4) = y1(i1, j1 + 1)
00623             if (     (xp(1) > xymiss-eps .and. xp(1) < xymiss+eps) &
00624             & .or. (xp(2) > xymiss-eps .and. xp(2) < xymiss+eps) &
00625             & .or. (xp(3) > xymiss-eps .and. xp(3) < xymiss+eps) &
00626             & .or. (xp(4) > xymiss-eps .and. xp(4) < xymiss+eps) &
00627             & .or. (yp(1) > xymiss-eps .and. yp(1) < xymiss+eps) &
00628             & .or. (yp(2) > xymiss-eps .and. yp(2) < xymiss+eps) &
00629             & .or. (yp(3) > xymiss-eps .and. yp(3) < xymiss+eps) &
00630             & .or. (yp(4) > xymiss-eps .and. yp(4) < xymiss+eps) ) cycle
00631             !
00632             ! Determine minimum and maximum X and Y of the cell
00633             !
00634             xpmin =  1.e10
00635             xpmax = -1.e10
00636             ypmin =  1.e10
00637             ypmax = -1.e10
00638             do ip = 1, 4
00639                xpmin = min(xp(ip), xpmin)
00640                xpmax = max(xp(ip), xpmax)
00641                ypmin = min(yp(ip), ypmin)
00642                ypmax = max(yp(ip), ypmax)
00643             enddo
00644             xpmean = .5*(xpmin + xpmax)
00645             ypmean = .5*(ypmin + ypmax)
00646             !
00647             ! First selection of points of grid2 that can be located in the cell
00648             !
00649             ! Find centre of the cell in tables Xs and Ys
00650             !
00651             call hunt(xs        ,n2        ,xpmean    ,lomnx     )
00652             call hunt(ys        ,n2        ,ypmean    ,lomny     )
00653             !
00654             ! For points with X-values between Xpmin and Xpmax set: iFlag(i)=1
00655             !
00656             lominx = lomnx
00657             lomaxx = lomnx
00658             do i = lomnx, 1, -1
00659                if (xs(i)>=xpmin) then
00660                   lominx        = i
00661                   iflag(nrx(i)) = 1
00662                else
00663                   exit
00664                endif
00665             enddo
00666             do i = lomnx + 1, n2
00667                if (xs(i)<=xpmax) then
00668                   lomaxx        = i
00669                   iflag(nrx(i)) = 1
00670                else
00671                   exit
00672                endif
00673             enddo
00674             !
00675             ! For the points with Y-values between Ypmin and Ypmax,
00676             ! that also lie between Xpmin and Xpmax: Save them in NrIn
00677             !
00678             iin = 1
00679             do i = lomny, 1, -1
00680                if (ys(i)>=ypmin) then
00681                   nrin(iin) = nry(i)*iflag(nry(i))
00682                   iin       = iin + iflag(nry(i))
00683                else
00684                   exit
00685                endif
00686             enddo
00687             do i = lomny + 1, n2
00688                if (ys(i)<=ypmax) then
00689                   nrin(iin) = nry(i)*iflag(nry(i))
00690                   iin       = iin + iflag(nry(i))
00691                else
00692                   exit
00693                endif
00694             enddo
00695             nin = iin - 1
00696             !
00697             ! Put iFlag back to 0
00698             !
00699             do i = lominx, lomaxx
00700                if (i/=0) iflag(nrx(i)) = 0
00701             enddo
00702             !
00703             ! Check whether selected points of grid2 lie within the cell
00704             ! using subroutine IPON; if so, determine weights W of the surrounding
00705             ! values in grid1 using subroutine INTRP4. Save the weights in Wtab
00706             ! The reference to grid1 is saved in arrays Iref and Jref.
00707             !
00708             do iin = 1, nin
00709                i2 = nrin(iin)
00710                inout = -1
00711                call ipon(xp        ,yp        ,4         ,x2(i2)    , &
00712                &          y2(i2)    ,inout     )
00713                if (inout>=0) then
00714                   !
00715                   ! Check on point with nonsense information on source grid 1;
00716                   ! This depends on agreements
00717                   !
00718                   if (      (code(i1    , j1    )==1 .or. code(i1    , j1    )==3) &
00719                   & .and. (code(i1 + 1, j1    )==1 .or. code(i1 + 1, j1    )==3) &
00720                   & .and. (code(i1 + 1, j1 + 1)==1 .or. code(i1 + 1, j1 + 1)==3) &
00721                   & .and. (code(i1    , j1 + 1)==1 .or. code(i1    , j1 + 1)==3) ) then
00722                      !
00723                      ! grid2 point is covered by 4 valid grid1 points
00724                      !
00725                      covered(i2) = 1
00726                      call bilin5(xp, yp, x2(i2), y2(i2), hbuff, ier)
00727                      w(:, i2) = real(hbuff(:),4)
00728                      !
00729                      iref(1, i2) = i1 + (j1 - 1)*m1
00730                      iref(2, i2) = i1 + 1 + (j1 - 1)*m1
00731                      iref(3, i2) = i1 + 1 + j1*m1
00732                      iref(4, i2) = i1 + j1*m1
00733                   elseif (code(i1, j1)>0 .and. code(i1 + 1, j1)>0 .and. &
00734                   & code(i1 + 1, j1 + 1)>0 .and. code(i1, j1 + 1)>0) then
00735                      !
00736                      ! Grid2 point is covered by 4 valid grid1 points, containing
00737                      ! one or more boundary points:
00738                      ! - do not use grid1 values
00739                      ! - use extrapolation values
00740                      !
00741                      covered(i2) = 0
00742                   else
00743                      !
00744                      ! Grid2 point is not covered by 4 valid grid1 points:
00745                      ! - do not use grid1 values
00746                      ! - do not use extrapolation values
00747                      !
00748                      covered(i2) = -1
00749                   endif
00750                endif
00751             enddo
00752          enddo
00753       enddo
00754 
00755    end subroutine make_map
00756 
00757    subroutine mkmap_step (x1        ,y1        ,m1        ,n1        ,    &
00758    &       alfaz     ,dsu       ,dnv       ,               &
00759    &       x2        ,y2        ,n2        ,w         ,  iref      )
00760       !!--description-----------------------------------------------------------------
00761       !
00762       !
00763       !     SUBROUTINE MKMAP_STEP
00764       !     Interpolation of curvilinear, numerically ordered grid (grid1)
00765       !     to random points, with weighting points (grid2).
00766       !
00767       !     J.A. Roelvink
00768       !     UNESCO-IHE / Deltares
00769       !     8 May 2013
00770       !
00771       !     Given: numerically ordered grid M1*N1
00772       !     with (new)coordinates X1 (1:M1,1:N1)
00773       !                  and Y1 (1:M1,1:N1)
00774       !
00775       !     Also given: random points X2(1:N2)
00776       !                           and Y2(1:N2)
00777       !                 previous iref
00778       !
00779       !     To be determined:  weighting factors and updated pointers for bilinear interpolation
00780       !     Weighting factors and locations of the requested (random) points in the
00781       !     ordered grid are saved in resp.
00782       !     W(1:4,1:N2) and Iref(1:4,1:N2)
00783       !
00784       !!--pseudo code and references--------------------------------------------------
00785       ! NONE
00786       !!--declarations----------------------------------------------------------------
00787       !
00788       implicit none
00789       !
00790       ! Global variables
00791       !
00792       integer                    , intent(in)  :: m1
00793       integer                    , intent(in)  :: n1
00794       integer                                  :: n2
00795       integer , dimension(4 , n2)              :: iref
00796       real*8  , dimension(4 , n2)              :: w
00797       real*8  , dimension(m1, n1), intent(in)  :: x1
00798       real*8  , dimension(m1, n1), intent(in)  :: y1
00799       real*8  , dimension(m1, n1), intent(in)  :: alfaz
00800       real*8  , dimension(m1, n1), intent(in)  :: dsu
00801       real*8  , dimension(m1, n1), intent(in)  :: dnv
00802       real*8  , dimension(n2)                  :: x2
00803       real*8  , dimension(n2)                  :: y2
00804       real*8                                   :: dx
00805       real*8                                   :: dy
00806       real*8                                   :: ds
00807       real*8                                   :: dn
00808       real*8                                   :: dsrel
00809       real*8                                   :: dnrel
00810       integer                                  :: i1,j1,i2
00811 
00812       do i2=1,n2
00813          if (iref(1,i2)>0) then
00814             i1=mod(iref(1,i2)-1,m1)+1
00815             j1=(iref(1,i2)-i1)/m1+1
00816             dx=x2(i2)-x1(i1,j1)
00817             dy=y2(i2)-y1(i1,j1)
00818             ds= dx*cos(alfaz(i1,j1))+dy*sin(alfaz(i1,j1))
00819             dn=-dx*sin(alfaz(i1,j1))+dy*cos(alfaz(i1,j1))
00820             dsrel=ds/dsu(i1,j1)
00821             dnrel=dn/dnv(i1,j1)
00822             i1=i1+floor(dsrel)
00823             j1=j1+floor(dnrel)
00824             dsrel=dsrel-floor(dsrel)
00825             dnrel=dnrel-floor(dnrel)
00826             iref(1, i2) = i1 + (j1 - 1)*m1
00827             iref(2, i2) = i1 + 1 + (j1 - 1)*m1
00828             iref(3, i2) = i1 + 1 + j1*m1
00829             iref(4, i2) = i1 + j1*m1
00830             w(1, i2) = (1.d0-dsrel)*(1.d0-dnrel)
00831             w(2, i2) =       dsrel *(1.d0-dnrel)
00832             w(3, i2) =       dsrel *      dnrel
00833             w(4, i2) = (1.d0-dsrel)*      dnrel
00834          endif
00835       enddo
00836 
00837    end subroutine mkmap_step
00838 
00839    subroutine grmap(f1        ,n1        ,f2        ,n2        ,iref      , &
00840    & w         ,np        ,iprint    )
00841       !!--description-----------------------------------------------------------------
00842       !
00843       ! compute interpolated values for all points on grid 2
00844       !
00845       ! special treatment of points on grid 2 that are outside
00846       ! grid 1; in that case iref(1,i2)=0 AND w(ip,i2)=0 for all ip
00847       !
00848       ! Iref(1,i2)   i1    ifac   F2(i2)*ifac     Result
00849       !
00850       !      0        1      1      F2(i2)        Old value is kept
00851       !    j,j>0      j      0       0.           F2 is initialized
00852       !
00853       !!--pseudo code and references--------------------------------------------------
00854       ! NONE
00855       !!--declarations----------------------------------------------------------------
00856       implicit none
00857       !
00858       ! Global variables
00859       !
00860       integer                   , intent(in)  :: iprint
00861       integer                   , intent(in)  :: n1
00862       integer                   , intent(in)  :: n2
00863       integer                   , intent(in)  :: np
00864       integer, dimension(np, n2), intent(in)  :: iref
00865       real*8 , dimension(n1)    , intent(in)  :: f1
00866       real*8 , dimension(n2)                  :: f2
00867       real*8 , dimension(np, n2), intent(in)  :: w
00868       !
00869       ! Local variables
00870       !
00871       integer :: i
00872       integer :: i1
00873       integer :: i2
00874       integer :: ip
00875       !
00876       !! executable statements -------------------------------------------------------
00877       !
00878       if (iprint==1) write (*, *) 'in grmap n1 n2', n1, n2
00879       do i2 = 1, n2
00880          i = iref(1, i2)
00881          if (i>0) then
00882             f2(i2)=0.d0
00883             !        i1 = max(i, 1)
00884             !        ifac = 1 - i/i1
00885             !        f2(i2) = f2(i2)*ifac
00886             !
00887             ! Function values at grid 2 are expressed as weighted average
00888             ! of function values in Np surrounding points of grid 1
00889             !
00890             if (iprint==1 .and. i2<=n2) &
00891             & write (*, '(1X,A,I6,4(1X,E10.4))') ' i2 w ', i2, (w(ip, i2) , ip = 1,  &
00892             & np)
00893             do ip = 1, np
00894                i = iref(ip, i2)
00895                i1 = max(i, 1)
00896                if (iprint==1 .and. i2<=n2) write (*, *) ' i1,f1(i1) ', i1, f1(i1)
00897                f2(i2) = f2(i2) + w(ip, i2)*f1(i1)
00898             enddo
00899          endif
00900       enddo
00901    end subroutine grmap
00902 
00903    subroutine grmap2(f1, cellsz1i     , n1        ,f2  ,cellsz2,  n2        ,iref      , &
00904    & w         ,np     )
00905       !!--description-----------------------------------------------------------------
00906       !
00907       ! compute interpolated values for all points on grid 1 given reference table
00908       ! for grid 2; this works the other way round from GRMAP. Assumption is that
00909       ! grid 2 is much finer than grid 1. For each point in grid 2 we know the
00910       ! surrounding points in grid 1 and the related weights. Instead of using this to
00911       ! interpolate from 1 to 2 we now integrate from 2 to 1 using the same weights.
00912       !
00913       !
00914       !!--pseudo code and references--------------------------------------------------
00915       ! NONE
00916       !!--declarations----------------------------------------------------------------
00917       implicit none
00918       !
00919       ! Global variables
00920       !
00921       integer                   , intent(in)  :: n1
00922       integer                   , intent(in)  :: n2
00923       integer                   , intent(in)  :: np
00924       integer, dimension(np, n2), intent(in)  :: iref
00925       real*8 , dimension(n1)                  :: f1
00926       real*8 , dimension(n1)    , intent(in)  :: cellsz1i   !array with 1/cell size
00927       real*8                    , intent(in)  :: cellsz2
00928       real*8 , dimension(n2)    , intent(in)  :: f2
00929       real*8 , dimension(np, n2), intent(in)  :: w
00930       !
00931       ! Local variables
00932       !
00933       integer :: i1
00934       integer :: i2
00935       integer :: ip
00936       !
00937       !! executable statements -------------------------------------------------------
00938       !
00939       do ip = 1, np
00940          do i2=1,n2
00941             i1 = iref(ip, i2)
00942             if (i1>0) then
00943                !f2(i2) = f2(i2) + w(ip, i2)*f1(i1)
00944                f1(i1) = f1(i1) + w(ip, i2)*f2(i2)*cellsz2*cellsz1i(i1)
00945             endif
00946          enddo
00947       enddo
00948    end subroutine grmap2
00949 
00950    subroutine ipon(xq     ,yq     ,n      ,xp     ,yp     ,inout     )
00951       !--description----------------------------------------------------------------
00952       !
00953       ! Deltares                                                               *
00954       ! AUTHOR : J.A.ROELVINK                                                  *
00955       ! DATE   : 22-12-1988                                                    *
00956       ! DETERMINE WHETHER POINT (xp,yp) LIES IN POLYGON (x,y) OF n POINTS      *
00957       ! POINT n+1 IS SET EQUAL TO POINT 1                                      *
00958       ! (ARRAY MUST HAVE DIMENSION n+1 IN MAIN PROGRAMME                       *
00959       ! inpout = -1 :  OUTSIDE POLYGON                                         *
00960       ! inpout =  0 :  ON EDGE OF POLYGON                                      *
00961       ! inpout =  1 :  INSIDE POLYGON                                          *
00962       ! USED METHOD :         - DRAW A VERTICAL LINE THROUGH (xp,yp)           *
00963       !                       - DETERMINE NUMBER OF INTERSECTIONS WITH POLYGON *
00964       !                         UNDER yp : nunder                              *
00965       !                       - IF nunder IS EVEN, THEN THE POINT LIES OUTSIDE *
00966       !                         THE POLYGON, OTHERWISE IT LIES INSIDE          *
00967       !                       - THE EDGE IS TREATED SEPARATELY                 *
00968       !
00969       !--pseudo code and references-------------------------------------------------
00970       ! NONE
00971       !--declarations---------------------------------------------------------------
00972       !
00973       implicit none
00974       !
00975       ! Global variables
00976       !
00977       integer               , intent(out) :: inout
00978       integer               , intent(in)  :: n
00979       real*8                , intent(in)  :: xp
00980       real*8                , intent(in)  :: yp
00981       real*8  , dimension(*)              :: xq
00982       real*8  , dimension(*)              :: yq
00983       !
00984       ! Local variables
00985       !
00986       integer                             :: i
00987       integer                             :: ierr
00988       integer                             :: nunder
00989       real*4                              :: ysn
00990       real*4  , dimension(:), allocatable :: x
00991       real*4  , dimension(:), allocatable :: y
00992       !
00993       ! executable statements ------------------------------------------------------
00994       !
00995       allocate(x(n+1))
00996       allocate(y(n+1))
00997       do i = 1, n
00998          x(i) = real( xq(i)-xp , 4)
00999          y(i) = real( yq(i)-yp , 4)
01000       enddo
01001       x(n + 1) = x(1)
01002       y(n + 1) = y(1)
01003       nunder   = 0
01004       do i = 1, n
01005          if ((x(i)<0. .and. x(i + 1)>=0.).or.(x(i + 1)<0. .and. x(i)>=0.)) then
01006             if (y(i)<0. .and. y(i + 1)<0.) then
01007                nunder = nunder + 1
01008             elseif ((y(i)<=0. .and. y(i + 1)>=0.) .or.                       &
01009             & (y(i + 1)<=0. .and. y(i)>=0.)) then
01010                ysn = (y(i)*x(i + 1) - x(i)*y(i + 1))/(x(i + 1) - x(i))
01011                if (ysn<0.) then
01012                   nunder = nunder + 1
01013                elseif (ysn<=0.) then
01014                   !
01015                   ! Edge
01016                   !
01017                   inout = 0
01018                   goto 100
01019                else
01020                endif
01021             else
01022             endif
01023          elseif (abs(x(i))<1.0E-8 .and. abs(x(i + 1))<1.0E-8) then
01024             if ((y(i)<=0. .and. y(i + 1)>=0.).or.(y(i + 1)<=0..and.y(i)>=0.)) &
01025             & then
01026                !
01027                ! Edge
01028                !
01029                inout = 0
01030                goto 100
01031             endif
01032          else
01033          endif
01034       enddo
01035       if (mod(nunder, 2)==0) then
01036          !
01037          ! Outside
01038          !
01039          inout = -1
01040       else
01041          !
01042          ! Inside
01043          !
01044          inout = 1
01045       endif
01046 100   continue
01047       deallocate(x, stat=ierr)
01048       deallocate(y, stat=ierr)
01049    end subroutine ipon
01050 
01051    subroutine hunt(xx        ,n         ,x         ,jlo       )
01052       !!--description-----------------------------------------------------------------
01053       ! NONE
01054       !!--pseudo code and references--------------------------------------------------
01055       ! NONE
01056       !!--declarations----------------------------------------------------------------
01057       !
01058       implicit none
01059       !
01060       ! Global variables
01061       !
01062       integer                                  :: jlo
01063       integer                    , intent(in)  :: n
01064       real*8              , intent(in)  :: x
01065       real*8, dimension(n), intent(in)  :: xx
01066       !
01067       ! Local variables
01068       !
01069       integer :: inc
01070       integer :: jhi
01071       integer :: jm
01072       logical :: ascnd
01073       !
01074       !! executable statements -------------------------------------------------------
01075       !
01076       ascnd = xx(n)>=xx(1)
01077       if (jlo<=0 .or. jlo>n) then
01078          jlo = 0
01079          jhi = n + 1
01080          goto 3
01081       endif
01082       inc = 1
01083       if (x>=xx(jlo) .eqv. ascnd) then
01084 1        continue
01085          jhi = jlo + inc
01086          if (jhi>n) then
01087             jhi = n + 1
01088          elseif (x>=xx(jhi) .eqv. ascnd) then
01089             jlo = jhi
01090             inc = inc + inc
01091             goto 1
01092          else
01093          endif
01094       else
01095          jhi = jlo
01096 2        continue
01097          jlo = jhi - inc
01098          if (jlo<1) then
01099             jlo = 0
01100          elseif (x<xx(jlo) .eqv. ascnd) then
01101             jhi = jlo
01102             inc = inc + inc
01103             goto 2
01104          else
01105          endif
01106       endif
01107 3     continue
01108       if (jhi - jlo==1) then
01109          return
01110       endif
01111       jm = (jhi + jlo)/2
01112       if (x>xx(jm) .eqv. ascnd) then
01113          jlo = jm
01114       else
01115          jhi = jm
01116       endif
01117       goto 3
01118    end subroutine hunt
01119 
01120    subroutine indexx(n         ,arrin     ,indx      )
01121       !----- GPL ---------------------------------------------------------------------
01122       !
01123       !  Copyright (C)  Stichting Deltares, 2011.
01124       !
01125       !  This program is free software: you can redistribute it and/or modify
01126       !  it under the terms of the GNU General Public License as published by
01127       !  the Free Software Foundation version 3.
01128       !
01129       !  This program is distributed in the hope that it will be useful,
01130       !  but WITHOUT ANY WARRANTY; without even the implied warranty of
01131       !  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
01132       !  GNU General Public License for more details.
01133       !
01134       !  You should have received a copy of the GNU General Public License
01135       !  along with this program.  If not, see <http://www.gnu.org/licenses/>.
01136       !
01137       !  contact: delft3d.support@deltares.nl
01138       !  Stichting Deltares
01139       !  P.O. Box 177
01140       !  2600 MH Delft, The Netherlands
01141       !
01142       !  All indications and logos of, and references to, "Delft3D" and "Deltares"
01143       !  are registered trademarks of Stichting Deltares, and remain the property of
01144       !  Stichting Deltares. All rights reserved.
01145       !
01146       !-------------------------------------------------------------------------------
01147       !  $Id: interp.F90 5598 2019-12-09 10:21:29Z ridde_mo $
01148       !  $HeadURL: https://svn.oss.deltares.nl/repos/xbeach/trunk/src/xbeachlibrary/interp.F90 $
01149       !!--description-----------------------------------------------------------------
01150       ! NONE
01151       !!--pseudo code and references--------------------------------------------------
01152       ! NONE
01153       !!--declarations----------------------------------------------------------------
01154       !
01155       implicit none
01156       !
01157       ! Global variables
01158       !
01159       integer                       , intent(in)  :: n
01160       integer, dimension(n)                       :: indx
01161       real*8   , dimension(n), intent(in)  :: arrin
01162       !
01163       ! Local variables
01164       !
01165       integer :: i
01166       integer :: indxt
01167       integer :: ir
01168       integer :: j
01169       integer :: l
01170       real*8 :: q
01171       !
01172       !! executable statements -------------------------------------------------------
01173       !
01174       do j = 1, n
01175          indx(j) = j
01176       enddo
01177       l = n/2 + 1
01178       ir = n
01179 10    continue
01180       if (l>1) then
01181          l = l - 1
01182          indxt = indx(l)
01183          q = arrin(indxt)
01184       else
01185          indxt = indx(ir)
01186          q = arrin(indxt)
01187          indx(ir) = indx(1)
01188          ir = ir - 1
01189          if (ir==1) then
01190             indx(1) = indxt
01191             return
01192          endif
01193       endif
01194       i = l
01195       j = l + l
01196 20    continue
01197       if (j<=ir) then
01198          if (j<ir) then
01199             if (arrin(indx(j))<arrin(indx(j + 1))) j = j + 1
01200          endif
01201          if (q<arrin(indx(j))) then
01202             indx(i) = indx(j)
01203             i = j
01204             j = j + j
01205          else
01206             j = ir + 1
01207          endif
01208          goto 20
01209       endif
01210       indx(i) = indxt
01211       goto 10
01212    end subroutine indexx
01213 
01214    subroutine bilin5(xa, ya, x0, y0, w, ier)
01215       !!--description-----------------------------------------------------------------
01216       ! NONE
01217       !!--pseudo code and references--------------------------------------------------
01218       !
01219       ! Author: H. Petit
01220       !
01221       !!--declarations----------------------------------------------------------------
01222       !
01223       implicit none
01224       !
01225       ! Global variables
01226       !
01227       integer               , intent(out) :: ier
01228       real*8                , intent(in)  :: x0
01229       real*8                , intent(in)  :: y0
01230       real*8  , dimension(4), intent(out) :: w
01231       real*8  , dimension(4), intent(in)  :: xa
01232       real*8  , dimension(4), intent(in)  :: ya
01233       !
01234       ! Local variables
01235       !
01236       real*8   :: a
01237       real*8   :: a21
01238       real*8   :: a22
01239       real*8   :: a31
01240       real*8   :: a32
01241       real*8   :: a41
01242       real*8   :: a42
01243       real*8   :: b
01244       real*8   :: c
01245       real*8   :: det
01246       real*8   :: discr
01247       real*8   :: eta
01248       real*8   :: x
01249       real*8   :: x1
01250       real*8   :: x2
01251       real*8   :: x3
01252       real*8   :: x3t
01253       real*8   :: x4
01254       real*8   :: xi
01255       real*8   :: xt
01256       real*8   :: y
01257       real*8   :: y1
01258       real*8   :: y2
01259       real*8   :: y3
01260       real*8   :: y3t
01261       real*8   :: y4
01262       real*8   :: yt
01263       !
01264       !! executable statements -------------------------------------------------------
01265       !
01266       ! read(12,*)x1,y1,f1
01267       x1 = xa(1)
01268       y1 = ya(1)
01269       ! read(12,*)x2,y2,f2
01270       x2 = xa(2)
01271       y2 = ya(2)
01272       ! read(12,*)x3,y3,f3
01273       x3 = xa(3)
01274       y3 = ya(3)
01275       ! read(12,*)x4,y4,f4
01276       x4 = xa(4)
01277       y4 = ya(4)
01278       x  = x0
01279       y  = y0
01280       !
01281       ! The bilinear interpolation problem is first transformed
01282       ! to the quadrangle with nodes (0,0),(1,0),(x3t,y3t),(0,1)
01283       ! and required location (xt,yt)
01284       !
01285       a21 = x2 - x1
01286       a22 = y2 - y1
01287       a31 = x3 - x1
01288       a32 = y3 - y1
01289       a41 = x4 - x1
01290       a42 = y4 - y1
01291       det = a21*a42 - a22*a41
01292       if (abs(det) < 1.0e-20) then
01293          ier = 1
01294          goto 99999
01295       endif
01296       x3t = (  a42*a31      - a41*a32     ) / det
01297       y3t = ( -a22*a31      + a21*a32     ) / det
01298       xt  = (  a42*(x - x1) - a41*(y - y1)) / det
01299       yt  = ( -a22*(x - x1) + a21*(y - y1)) / det
01300       if ((x3t < 0.0) .or. (y3t < 0.0)) then
01301          ! write (*, *) 'distorted quadrangle'
01302          ier = 1
01303          goto 99999
01304       endif
01305       if (abs(x3t - 1.0d0) < 1.0e-7) then
01306          xi = xt
01307          if (abs(y3t - 1.0d0) < 1.0e-7) then
01308             eta = yt
01309          elseif (abs(1.0d0 + (y3t - 1.0d0)*xt) < 1.0e-6) then
01310             ! write (*, *) 'extrapolation over too large a distance'
01311             ier = 1
01312             goto 99999
01313          else
01314             eta = yt / (1.0d0 + (y3t - 1.0d0)*xt)
01315          endif
01316       elseif (abs(y3t - 1.0d0) < 1.0e-6) then
01317          eta = yt
01318          if (abs(1.0d0 + (x3t - 1.0d0)*yt) < 1.0e-6) then
01319             ! write (*, *) 'extrapolation over too large a distance'
01320             ier = 1
01321             goto 99999
01322          else
01323             xi = xt / (1.0d0 + (x3t - 1.0d0)*yt)
01324          endif
01325       else
01326          a     = y3t - 1.0d0
01327          b     = 1.0d0 + (x3t - 1.0d0)*yt - (y3t - 1.0d0)*xt
01328          c     = -xt
01329          discr = b*b - 4.0d0*a*c
01330          if (discr < 1.0e-6) then
01331             ! write (*, *) 'extrapolation over too large a distance'
01332             ier = 1
01333             goto 99999
01334          endif
01335          xi  = (-b + sqrt(discr)) / (2.0d0*a)
01336          eta = ((y3t - 1.0d0)*(xi - xt) + (x3t - 1.0d0)*yt) / (x3t - 1.0d0)
01337       endif
01338       w(1) = (1.0d0-xi) * (1.0d0-eta)
01339       w(2) =         xi  * (1.0d0-eta)
01340       w(3) =         xi  *         eta
01341       w(4) =        eta  * (1.0d0-xi )
01342       return
01343 99999 continue
01344    end subroutine bilin5
01345 
01346    subroutine sort(n         ,ra        ,wksp      ,iwksp     )
01347       !!--description-----------------------------------------------------------------
01348       ! Sorts an array, routine from Numerical Recipes
01349       !!--pseudo code and references--------------------------------------------------
01350       ! NONE
01351       !!--declarations----------------------------------------------------------------
01352       !
01353       implicit none
01354       !
01355       ! Global variables
01356       !
01357       integer                                     :: n
01358       integer, dimension(n)                       :: iwksp
01359       real*8   , dimension(n)              :: ra
01360       real*8   , dimension(n), intent(out) :: wksp
01361       !
01362       ! Local variables
01363       !
01364       integer :: j
01365       !
01366       !! executable statements -------------------------------------------------------
01367       !
01368       call indexx(n         ,ra        ,iwksp     )
01369       do j = 1, n
01370          wksp(j) = ra(iwksp(j))
01371       enddo
01372    end subroutine sort
01373 
01374    subroutine trapezoidal(x,y,n,x1_in,x2_in,integ)
01375       ! Compute integral over function y(x) from x1 to x2
01376       ! x is equidistant
01377       !(c)2014 Dano Roelvink
01378       implicit none
01379       integer,              intent(in)    :: n
01380       real*8, dimension(n), intent(in)    :: x,y          ! arrays x and y(x)
01381       real*8,               intent(in)    :: x1_in,x2_in  ! integration limits
01382       real*8,               intent(out)   :: integ        ! integral
01383       real*8                              :: x1,y1,x2,y2,Ifirst,Imid,Ilast,dx
01384       integer                             :: i1,i2,i,i1p1,i2p1
01385       if (x1_in>x(n).or.x2_in<x(1)) then
01386          integ=0
01387       else
01388 
01389          x1=max(x1_in,x(1)+1d-60)
01390          x2=min(x2_in,x(n)-1d-60)
01391          dx=(x(n)-x(1))/(n-1)
01392          i1=floor((x1-x(1))/dx)+1
01393          i2=floor((x2-x(1))/dx)+1
01394          i1p1=min(i1+1,n)
01395          i2p1=min(i2+1,n)
01396          ! first partial trapezoid
01397          y1=y(i1)+(x1-x(i1))/dx*(y(i1p1)-y(i1))
01398          Ifirst=.5*(x(i1p1)-x1)*(y(i1p1)+y1)
01399          ! middle part
01400          Imid=.5*y(i1p1)
01401          do i=i1+2,i2-1
01402             Imid=Imid+y(i)
01403          end do
01404          Imid=Imid+.5*y(i2)
01405          Imid=Imid*dx
01406          ! last partial trapezoid
01407          y2=y(i2)+(x2-x(i2))/dx*(y(i2p1)-y(i2))
01408          Ilast=.5*(x2-x(i2))*(y2+y(i2))
01409          integ=Ifirst+Imid+Ilast
01410       endif
01411    end subroutine trapezoidal
01412 
01413    subroutine trapezoidal_cyclic(x,y,n,xcycle,x1,x2,integ)
01414       ! Compute integral over function y(x) from x1 to x2
01415       ! x is equidistant, function is cyclic so y(x+k*xcycle)=y(x)
01416       !(c)2014 Dano Roelvink
01417       implicit none
01418       integer,              intent(in)    :: n
01419       real*8, dimension(n), intent(in)    :: x,y          ! arrays x and y(x)
01420       real*8,               intent(in)    :: x1,x2,xcycle ! integration limits,cycle length
01421       real*8,               intent(out)   :: integ          ! integral
01422       real*8, dimension(:),allocatable    :: xp,yp
01423       real*8                              :: dx
01424       integer                             :: ip,indt,np
01425 
01426       dx=x(2)-x(1)
01427       np=floor(x2/dx)-(floor(x1/dx)+1)+2
01428       allocate(xp(np))
01429       allocate(yp(np))
01430       xp(1)=x1
01431       do ip=2,np-1
01432          xp(ip)=(floor(x1/dx)+ip-1)*dx
01433       end do
01434       xp(np)=x2
01435       if (xcycle>0) then
01436          call interp_in_cyclic_function(x,y,n,xcycle,xp,np,yp)
01437       else
01438          do ip=1,np
01439             call linear_interp (x,y,n,xp(ip),yp(ip),indt)
01440          end do
01441       endif
01442       integ=0.d0
01443       do ip=1,np-1
01444          integ=integ+.5*(xp(ip+1)-xp(ip))*(yp(ip+1)+yp(ip))
01445       end do
01446 
01447       deallocate(xp)
01448       deallocate(yp)
01449 
01450    end subroutine trapezoidal_cyclic
01451 
01452    subroutine interp_using_trapez_rule(x,y,n,xcycle,xtarg,ytarg,ntarg)
01453       implicit none
01454       ! Compute integral over function y(x) from x1 to x2
01455       ! x is equidistant, function is cyclic so y(x+k*xcycle)=y(x)
01456       !(c)2014 Dano Roelvink
01457       integer,              intent(in)        :: n,ntarg
01458       real*8, dimension(n), intent(in)        :: x,y      ! arrays x and y(x)
01459       real*8,               intent(in)        :: xcycle   ! cycle length
01460       real*8, dimension(ntarg), intent(in)    :: xtarg    ! x values to interpolate to
01461       real*8, dimension(ntarg), intent(out)   :: ytarg    ! y values to interpolate to
01462       real*8                                  :: dx,x1,x2,integ
01463       integer                                 :: itarg
01464 
01465       dx=xtarg(2)-xtarg(1)
01466       do itarg=1,ntarg
01467          x1=xtarg(itarg)-.5*dx
01468          x2=xtarg(itarg)+.5*dx
01469          call trapezoidal_cyclic(x,y,n,xcycle,x1,x2,integ)
01470          ytarg(itarg)=integ/dx
01471       end do
01472 
01473    end subroutine interp_using_trapez_rule
01474 
01475    subroutine interp_in_cyclic_function(x,y,n,xcycle,xp,np,yp)
01476       implicit none
01477       integer,               intent(in)    :: n
01478       real*8, dimension(n),  intent(in)    :: x,y          ! arrays x and y(x)
01479       real*8, dimension(:), allocatable    :: xc,yc        ! complemented cyclic arrays
01480       real*8,                intent(in)    :: xcycle       ! cycle length
01481       integer,               intent(in)    :: np
01482       real*8, dimension(np), intent(in)    :: xp           ! points to interpolate to
01483       real*8, dimension(np), intent(out)   :: yp                 ! interpolated yp values
01484       integer                              :: icycle,ip,ileft,iright,nc,i
01485       real*8                               :: dx,yleft,yright,facleft,facright
01486 
01487       dx=x(2)-x(1)
01488       icycle=nint(xcycle/dx)
01489       allocate(xc(icycle+1))
01490       allocate(yc(icycle+1))
01491       if (n>icycle+1) then
01492          ! nonsense; error
01493       elseif (n==icycle+1) then
01494          ! e.g. 0, 30, 60,...360
01495          xc(1:n)=x
01496          yc(1:n)=y
01497       elseif (n==icycle) then
01498          ! e.g. 30, 60 ...360 or 15, 45 ...345 with n=12 and icycle=12
01499          ! interpolate between n-th and 1st value
01500          xc(1:n)=x
01501          yc(1:n)=y
01502          xc(n+1)=xc(n)+dx
01503          yc(n+1)=yc(1)
01504       elseif (n<icycle) then
01505          ! do not interpolate between n-th and 1st value; set values in gap to 0
01506          xc(1:n)=x
01507          yc(1:n)=y
01508          do i=n+1,icycle
01509             xc(i)=xc(i-1)+dx
01510             yc(i)=0.d0
01511          end do
01512          xc(icycle+1)=xc(icycle)+dx
01513          yc(icycle+1)=yc(1)
01514       endif
01515 
01516       nc=icycle+1
01517 
01518       do ip=1,np
01519          ileft=floor((xp(ip)-xc(1))/dx)+1
01520          do while (ileft<1)
01521             ileft=ileft+icycle
01522          end do
01523          do while (ileft>nc)
01524             ileft=ileft-icycle
01525          end do
01526          if (ileft>nc .or. ileft<1) then
01527             yleft=0
01528          else
01529             yleft=yc(ileft)
01530          endif
01531          iright=ileft+1
01532          do while (iright<1)
01533             iright=iright+icycle
01534          end do
01535          do while (iright>nc)
01536             iright=iright-icycle
01537          end do
01538          if (iright>nc .or. iright<1) then
01539             yright=0
01540          else
01541             yright=yc(iright)
01542          endif
01543          facright=mod(xp(ip),dx)/dx
01544          facleft=1.d0-facright
01545          yp(ip)=facleft*yleft+facright*yright
01546 
01547       end do
01548       deallocate(xc)
01549       deallocate(yc)
01550 
01551    end subroutine interp_in_cyclic_function
01552 
01553 end module interp
 All Classes Files Functions Variables Defines