subroutine rgrd4u interpolates the nx by ny by nz by nt array p onto the mx by my by mz by mt array q. it is assumed that p and q are values on uniform nx by ny by nz by nt and mx by my by mz by mt grids which are superimposed on the same box region (INCLUDING BOUNDARIES). if p and q are values on nonuniform orthogonal grids and/or if the grid on which q is defined lies within the p grid then subroutine rgrd4 should be used.
linear or cubic interpolation (see intpol) is used in each direction for which the q grid is not a subgrid of the p grid. [the mx (my,mz,mt) uniform grid is a subgrid of the nx (ny,nz,nt) uniform grid if and only if mx-1 (my-1,nz-1,nt-1) divides nx-1 (ny-1,nz-1,nt-1)]. Values are set directly without (the need for) interpolation in subgrid directions.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
integer, | intent(in) | :: | nx |
the integer first dimension of p. nx > 1 if intpol(1) = 1 or nx > 3 if intpol(1) = 3 is required (see ier = 2). |
||
integer, | intent(in) | :: | ny |
the integer second dimension of p. ny > 1 if intpol(2) = 1 or ny > 3 if intpol(2) = 3 is required (see ier = 2). |
||
integer, | intent(in) | :: | nz |
the integer third dimension of p. nz > 1 if intpol(3) = 1 or nz > 3 if intpol(3) = 3 is required (see ier = 2) |
||
integer, | intent(in) | :: | nt |
the integer fourth dimension of p. nt > 1 if intpol(4) = 1 or nt > 3 if intpol(4) = 3 is required (see ier=2) |
||
real(kind=wp), | intent(in) | :: | p(nx,ny,nz,nt) |
a real(wp) nx by ny by nz by nt array of given values |
||
integer, | intent(in) | :: | mx |
the integer first dimension of q. mx > 1 is required (see ier = 1) |
||
integer, | intent(in) | :: | my |
the integer second dimension of q. my > 1 is required (see ier = 1) |
||
integer, | intent(in) | :: | mz |
the integer third dimension of q. mz > 1 is required (see ier = 1) |
||
integer, | intent(in) | :: | mt |
the integer fourth dimension of q. mt > 1 is required (see ier = 1) |
||
real(kind=wp), | intent(out) | :: | q(mx,my,mz,mt) |
a real(wp) mx by my by mz by mt array of values which are interpolated from p. |
||
integer, | intent(in) | :: | intpol(4) |
an integer vector of dimension 4 which sets linear or cubic interpolation in each of the x,y,z,t directions as follows:
values other than 1 or 3 in intpol are not allowed (ier = 3). |
||
real(kind=wp), | intent(inout) | :: | w(lw) |
a real(wp) work space of length at least lw which must be provided in the routine calling rgrd4u |
||
integer, | intent(in) | :: | lw |
the integer length of the work space w.
then lw must be greater than or equal to lwx+lwy+lwz+lwt |
||
integer, | intent(inout) | :: | iw(liw) |
an integer work space of length at least liw which must be provided in the routine calling rgrd4u |
||
integer, | intent(in) | :: | liw |
the integer length of the integer work space iw. liw must be at least mx+my+mz+mt |
||
integer, | intent(out) | :: | ier |
an integer error flag set as follows:
|
subroutine rgrd4u(nx,ny,nz,nt,p,mx,my,mz,mt,q,intpol,w,lw,iw,liw,ier) implicit none integer,intent(in) :: nx !! the integer first dimension of p. nx > 1 if intpol(1) = 1 or !! nx > 3 if intpol(1) = 3 is required (see ier = 2). integer,intent(in) :: ny !! the integer second dimension of p. ny > 1 if intpol(2) = 1 or !! ny > 3 if intpol(2) = 3 is required (see ier = 2). integer,intent(in) :: nz !! the integer third dimension of p. nz > 1 if intpol(3) = 1 or !! nz > 3 if intpol(3) = 3 is required (see ier = 2) integer,intent(in) :: nt !! the integer fourth dimension of p. nt > 1 if intpol(4) = 1 or !! nt > 3 if intpol(4) = 3 is required (see ier=2) integer,intent(in) :: mx !! the integer first dimension of q. mx > 1 is required (see ier = 1) integer,intent(in) :: my !! the integer second dimension of q. my > 1 is required (see ier = 1) integer,intent(in) :: mz !! the integer third dimension of q. mz > 1 is required (see ier = 1) integer,intent(in) :: mt !! the integer fourth dimension of q. mt > 1 is required (see ier = 1) integer,intent(in) :: intpol(4) !! an integer vector of dimension 4 which sets linear or cubic !! interpolation in each of the x,y,z,t directions as follows: !! !! * intpol(1) = 1 sets linear interpolation in the x direction !! * intpol(1) = 3 sets cubic interpolation in the x direction. !! * intpol(2) = 1 sets linear interpolation in the y direction !! * intpol(2) = 3 sets cubic interpolation in the y direction. !! * intpol(3) = 1 sets linear interpolation in the z direction !! * intpol(3) = 3 sets cubic interpolation in the z direction. !! * intpol(4) = 1 sets linear interpolation in the t direction !! * intpol(4) = 3 sets cubic interpolation in the t direction. !! !! values other than 1 or 3 in intpol are not allowed (ier = 3). integer,intent(in) :: liw !! the integer length of the integer work space iw. !! liw must be at least mx+my+mz+mt integer,intent(inout) :: iw(liw) !! an integer work space of length at least liw !! which must be provided in the routine calling rgrd4u integer,intent(in) :: lw !! the integer length of the work space w. !! !! * let lwx = 1 if mx-1 divides nx-1; otherwise !! let lwx = mx if intpol(1) = 1 or !! let lwx = 4*mx if intpol(1) = 3 !! * let lwy = 0 if my-1 divides ny-1; otherwise !! let lwy = my+2*mx if intpol(2) = 1 or !! let lwy = 4*(mx+my) if intpol(2) = 3 !! * let lwz = 0 if mz-1 divides nz-1; otherwise !! let lwz = 2*mx*my+mz if intpol(3) = 1 or !! let lwz = 4*(mx*my+mz) if intpol(3) = 3 !! * let lwt = 0 if mt-1 divides nt-1; otherwise !! let lwt = 2*mx*my*mz+mt if intpol(4) = 1 or !! let lwt = 4*(mx*my*mz+mt) if intpol(4) = 3 !! !! then lw must be greater than or equal to lwx+lwy+lwz+lwt integer,intent(out) :: ier !! an integer error flag set as follows: !! !! * ier = 0 if no errors in input arguments are detected !! * ier = 1 if min(mx,my,mz,mt) < 2 !! * ier = 2 if nx < 2 when intpol(1)=1 or nx < 4 when intpol(1)=3 (or) !! ny < 2 when intpol(2)=1 or ny < 4 when intpol(2)=3 (or) !! nz < 2 when intpol(3)=1 or nz < 4 when intpol(3)=3 (or) !! nt < 2 when intpol(4)=1 or nt < 4 when intpol(4)=3. !! * ier = 3 if any of intpol(1),intpol(2),intpol(3),intpol(4) is not !! equal to 1 or 3. !! * ier = 4 if lw or liw is too small (insufficient work space) real(wp),intent(in) :: p(nx,ny,nz,nt) !! a real(wp) nx by ny by nz by nt array of given values real(wp),intent(out) :: q(mx,my,mz,mt) !! a real(wp) mx by my by mz by mt array of values which are interpolated from p. real(wp),intent(inout) :: w(lw) !! a real(wp) work space of length at least lw !! which must be provided in the routine calling rgrd4u integer :: inmx,jnmy,knmz,lnmt,isubx,jsuby,ksubz,lsubt integer :: mxmy,mxmymz,lwx,lwy,lwz,lwt,jy,kz,lt integer :: i2,i3,i4,i5 integer :: j2,j3,j4,j5,j6,j7,j8,j9 integer :: k2,k3,k4,k5,k6,k7,k8,k9 integer :: l2,l3,l4,l5,l6,l7,l8,l9 ! check input arguments ! check mx,my,mz,mt ier = 1 if (min(mx,my,mz,mt) < 1) return ! check intpol ier = 3 if (intpol(1)/=1 .and. intpol(1)/=3) return if (intpol(2)/=1 .and. intpol(2)/=3) return if (intpol(3)/=1 .and. intpol(3)/=3) return if (intpol(4)/=1 .and. intpol(4)/=3) return ! check nx,ny,nz,nt ier = 2 if (intpol(1)==1 .and. nx<2) return if (intpol(1)==3 .and. nx<4) return if (intpol(2)==1 .and. ny<2) return if (intpol(2)==3 .and. ny<4) return if (intpol(3)==1 .and. nz<2) return if (intpol(3)==3 .and. nz<4) return if (intpol(4)==1 .and. nt<2) return if (intpol(4)==3 .and. nt<4) return ! set subgrid indicators inmx = (nx-1)/(mx-1) jnmy = (ny-1)/(my-1) knmz = (nz-1)/(mz-1) lnmt = (nt-1)/(mt-1) isubx = nx - inmx*(mx-1) jsuby = ny - jnmy*(my-1) ksubz = nz - knmz*(mz-1) lsubt = nt - lnmt*(mt-1) ! check work space length input ier = 4 mxmy = mx*my mxmymz = mxmy*mz lwx = 1 if (isubx/=1) then if (intpol(1)==1) then lwx = mx else lwx = 4*mx end if end if lwy = 0 if (jsuby/=1) then if (intpol(2)==1) then lwy = (2*mx+my) else lwy = 4*my+4*mx end if end if lwz = 0 if (ksubz/=1) then if (intpol(3)==1) then lwz = (2*mxmy+mz) else lwz = 4*mxmy+4*mz end if end if lwt = 0 if (lsubt/=1) then if (intpol(4)==1) then lwt = (2*mxmymz+mt) else lwt = 4*mxmymz+4*mt end if end if if (lw < lwx+lwy+lwz+lwt) return if (liw < mx+my+mz+mt) return ! arguments o.k. ier = 0 jy = mx+1 kz = mx+my+1 lt = mx+my+mz+1 if (intpol(4)==1) then ! linearly interpolate in nt, set work space pointers and scales l2 = 1 l3 = l2 l4 = l3+mt l5 = l4 l6 = l5 l7 = l6 l8 = l7+mxmymz l9 = l8+mxmymz call linmxu(nt,mt,iw(lt),w(l3)) k2 = l9 if (intpol(3)==1) then ! linear in z k3 = k2 k4 = k3+mz k5 = k4 k6 = k5 k7 = k6 k8 = k7+mxmy k9 = k8+mxmy call linmxu(nz,mz,iw(kz),w(k3)) j2 = k9 else ! cubic in z k3 = k2+mz k4 = k3+mz k5 = k4+mz k6 = k5+mz k7 = k6+mxmy k8 = k7+mxmy k9 = k8+mxmy call cubnmxu(nz,mz,iw(kz),w(k2),w(k3),w(k4),w(k5)) j2 = k9+mxmy end if if (intpol(2) == 1) then ! linear in y j3 = j2 j4 = j3+my j5 = j4 j6 = j5 j7 = j6 j8 = j7+mx j9 = j8+mx call linmxu(ny,my,iw(jy),w(j3)) i2 = j9 else ! cubic in y j3 = j2+my j4 = j3+my j5 = j4+my j6 = j5+my j7 = j6+mx j8 = j7+mx j9 = j8+mx call cubnmxu(ny,my,iw(jy),w(j2),w(j3),w(j4),w(j5)) i2 = j9+mx end if if (intpol(1) == 1) then ! linear in x i3 = i2 i4 = i3 i5 = i4 call linmxu(nx,mx,iw,w(i3)) else ! cubic in x i3 = i2+mx i4 = i3+mx i5 = i4+mx call cubnmxu(nx,mx,iw,w(i2),w(i3),w(i4),w(i5)) end if ! linearly interpolate in t call lint4u(nx,ny,nz,nt,p,mx,my,mz,mt,mxmy,mxmymz,q,intpol,& iw(lt),w(l3),w(l7),w(l8),& iw(kz),w(k2),w(k3),w(k4),w(k5),w(k6),w(k7),w(k8),w(k9),& iw(jy),w(j2),w(j3),w(j4),w(j5),w(j6),w(j7),w(j8),w(j9),& iw,w(i2),w(i3),w(i4),w(i5),& inmx,jnmy,knmz,lnmt,isubx,jsuby,ksubz,lsubt) else ! cubically interpolate in t l2 = 1 l3 = l2+mt l4 = l3+mt l5 = l4+mt l6 = l5+mt l7 = l6+mxmymz l8 = l7+mxmymz l9 = l8+mxmymz call cubnmxu(nt,mt,iw(lt),w(l2),w(l3),w(l4),w(l5)) k2 = l9+mxmymz if (intpol(3)==1) then ! linear in z k3 = k2 k4 = k3+mz k5 = k4 k6 = k5 k7 = k6 k8 = k7+mxmy k9 = k8+mxmy call linmxu(nz,mz,iw(kz),w(k3)) j2 = k9 else ! cubic in z k3 = k2+mz k4 = k3+mz k5 = k4+mz k6 = k5+mz k7 = k6+mxmy k8 = k7+mxmy k9 = k8+mxmy call cubnmxu(nz,mz,iw(kz),w(k2),w(k3),w(k4),w(k5)) j2 = k9+mxmy end if if (intpol(2) == 1) then j3 = j2 j4 = j3+my j5 = j4 j6 = j5 j7 = j6 j8 = j7+mx j9 = j8+mx call linmxu(ny,my,iw(jy),w(j3)) i2 = j9 else j3 = j2+my j4 = j3+my j5 = j4+my j6 = j5+my j7 = j6+mx j8 = j7+mx j9 = j8+mx call cubnmxu(ny,my,iw(jy),w(j2),w(j3),w(j4),w(j5)) i2 = j9+mx end if ! set work space portion and indices which depend on x interpolation if (intpol(1) == 1) then i3 = i2 i4 = i3 i5 = i4 call linmxu(nx,mx,iw,w(i3)) else i3 = i2+mx i4 = i3+mx i5 = i4+mx call cubnmxu(nx,mx,iw,w(i2),w(i3),w(i4),w(i5)) end if ! cubically interpolate in t call cubt4u(nx,ny,nz,nt,p,mx,my,mz,mt,mxmy,mxmymz,q,intpol,& iw(lt),w(l2),w(l3),w(l4),w(l5),w(l6),w(l7),w(l8),w(l9),& iw(kz),w(k2),w(k3),w(k4),w(k5),w(k6),w(k7),w(k8),w(k9),& iw(jy),w(j2),w(j3),w(j4),w(j5),w(j6),w(j7),w(j8),w(j9),& iw,w(i2),w(i3),w(i4),w(i5),& inmx,jnmy,knmz,lnmt,isubx,jsuby,ksubz,lsubt) end if end subroutine rgrd4u