subroutine rgrd4 interpolates the values p(i,j,k,l) on the orthogonal grid (x(i),y(j),z(k),t(l)) for i=1,...,nx;j=1,...,ny;k=1,...,nz;l=1,...,nt onto q(ii,jj,kk,ll) on the orthogonal grid (xx(ii),yy(jj),zz(kk),tt(ll)) for ii=1,...,mx;jj=1,...,my;kk=1,...,mz;ll=1,...,mt
linear or cubic interpolation is used (independently) in each direction (see argument intpol).
each of the x,y,z,t grids must be strictly montonically increasing and each of the xx,yy,zz,tt grids must be montonically increasing (see ier = 4). in addition the (X,Y,Z,T) region of the q grid
[xx(1),xx(mx)] X [yy(1),yy(my)] X [zz(1),zz(mz)] X [tt(1),tt(my)]
must lie within the (X,Y,Z,T) region of the p grid
[x(1),x(nx)] X [y(1),y(ny)] X [z(1),z(nz)] X [t(1),t(nt)].
extrapolation is not allowed (see ier=3). if these (X,Y,Z,T) regions are identical and the orthogonal grids are UNIFORM in each direction then subroutine rgrd4u should be used instead of rgrd4.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
integer, | intent(in) | :: | nx |
the integer dimension of the grid vector x and the first dimension of p. nx > 1 if intpol(1) = 1 or nx > 3 if intpol(1) = 3 is required. |
||
integer, | intent(in) | :: | ny |
the integer dimension of the grid vector y and the second dimension of p. ny > 1 if intpol(2) = 1 or ny > 3 if intpol(2) = 3 is required. |
||
integer, | intent(in) | :: | nz |
the integer dimension of the grid vector z and the third dimension of p. nz > 1 if intpol(3) = 1 or nz > 3 if intpol(3) = 3 is required. |
||
integer, | intent(in) | :: | nt |
the integer dimension of the grid vector t and the fourth dimension of p. nt > 1 if intpol(4) = 1 or nt > 3 if intpol(4) = 3 is required. |
||
real(kind=wp), | intent(in) | :: | x(nx) |
a real(wp) nx vector of strictly increasing values which defines the x portion of the orthogonal grid on which p is given |
||
real(kind=wp), | intent(in) | :: | y(ny) |
a real(wp) ny vector of strictly increasing values which defines the y portion of the orthogonal grid on which p is given |
||
real(kind=wp), | intent(in) | :: | z(nz) |
a real(wp) nz vector of strictly increasing values which defines the z portion of the orthogonal grid on which p is given |
||
real(kind=wp), | intent(in) | :: | t(nt) |
a real(wp) nt vector of strictly increasing values which defines the t portion of the orthogonal grid on which p is given |
||
real(kind=wp), | intent(in) | :: | p(nx,ny,nz,nt) |
a real(wp) nx by ny by nz by nt array of values given on the (x,y,z,t) grid |
||
integer, | intent(in) | :: | mx |
the integer dimension of the grid vector xx and the first dimension of q. mx > 0 is required. |
||
integer, | intent(in) | :: | my |
the integer dimension of the grid vector yy and the second dimension of q. my > 0 is required. |
||
integer, | intent(in) | :: | mz |
the integer dimension of the grid vector zz and the third dimension of q. mz > 0 is required. |
||
integer, | intent(in) | :: | mt |
the integer dimension of the grid vector tt and the fourth dimension of q. mt > 0 is required. |
||
real(kind=wp), | intent(in) | :: | xx(mx) |
a real(wp) mx vector of increasing values which defines the x portion of the orthogonal grid on which q is defined. xx(1) < x(1) or xx(mx) > x(nx) is not allowed (see ier = 3) |
||
real(kind=wp), | intent(in) | :: | yy(my) |
a real(wp) my vector of increasing values which defines the y portion of the orthogonal grid on which q is defined. yy(1) < y(1) or yy(my) > y(ny) is not allowed (see ier = 3) |
||
real(kind=wp), | intent(in) | :: | zz(mz) |
a real(wp) mz vector of increasing values which defines the z portion of the orthogonal grid on which q is defined. zz(1) < z(1) or zz(mz) > z(nz) is not allowed (see ier = 3) |
||
real(kind=wp), | intent(in) | :: | tt(mt) |
a real(wp) mt vector of increasing values which defines the t portion of the orthogonal grid on which q is defined. tt(1) < t(1) or tt(mt) > t(nt) is not allowed (see ier = 3) |
||
real(kind=wp), | intent(out) | :: | q(mx,my,mz,mt) |
a real(wp) mx by my by mz by mt array of values on the (xx,yy,zz,tt) grid which are interpolated from p on the (x,y,z,t) grid |
||
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 = 6). |
||
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 rgrd4 |
||
integer, | intent(in) | :: | lw |
the integer length of the real(wp) work space w. let
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 rgrd4 |
||
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 rgrd4(nx,ny,nz,nt,x,y,z,t,p,mx,my,mz,mt,xx,yy,zz,tt,q,intpol,w,lw,iw,liw,ier) implicit none integer,intent(in) :: nx !! the integer dimension of the grid vector x and the first dimension of p. !! nx > 1 if intpol(1) = 1 or nx > 3 if intpol(1) = 3 is required. integer,intent(in) :: ny !! the integer dimension of the grid vector y and the second dimension of p. !! ny > 1 if intpol(2) = 1 or ny > 3 if intpol(2) = 3 is required. integer,intent(in) :: nz !! the integer dimension of the grid vector z and the third dimension of p. !! nz > 1 if intpol(3) = 1 or nz > 3 if intpol(3) = 3 is required. integer,intent(in) :: nt !! the integer dimension of the grid vector t and the fourth dimension of p. !! nt > 1 if intpol(4) = 1 or nt > 3 if intpol(4) = 3 is required. integer,intent(in) :: mx !! the integer dimension of the grid vector xx and the first dimension !! of q. mx > 0 is required. integer,intent(in) :: my !! the integer dimension of the grid vector yy and the second dimension !! of q. my > 0 is required. integer,intent(in) :: mz !! the integer dimension of the grid vector zz and the third dimension !! of q. mz > 0 is required. integer,intent(in) :: mt !! the integer dimension of the grid vector tt and the fourth dimension !! of q. mt > 0 is required. integer,intent(in) :: lw !! the integer length of the real(wp) work space w. let !! !! * lwx = mx if intpol(1) = 1 !! * lwx = 4*mx if intpol(1) = 3 !! * lwy = my+2*mx if intpol(2) = 1 !! * lwy = 4*(my+mx) if intpol(2) = 3 !! * lwz = 2*mx*my+mz if intpol(3) = 1 !! * lwz = 4*(mx*my+mz) if intpol(3) = 3 !! * lwt = 2*mx*my*mz+mt if intpol(4) = 1 !! * 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(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: !! !! * ier = 0 if no errors in input arguments are detected !! * ier = 1 if min(mx,my,mz,mt) < 1 !! * 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 xx(1) < x(1) or x(nx) < xx(mx) (or) !! * yy(1) < y(1) or y(ny) < yy(my) (or) !! * zz(1) < z(1) or z(nz) < zz(mz) (or) !! * tt(1) < t(1) or t(nt) < tt(mt) !! to avoid this flag when end points are intended to be the !! same but may differ slightly due to roundoff error, they !! should be set exactly in the calling routine (e.g., if both !! grids have the same y boundaries then yy(1)=y(1) and yy(my)=y(ny) !! should be set before calling rgrd4) !! !! * ier = 4 if one of the grids x,y,z,t is not strictly monotonically !! increasing or if one of the grids xx,yy,zz,tt is not !! montonically increasing. more precisely if: !! !! * x(i+1) <= x(i) for some i such that 1 <= i < nx (or) !! * y(j+1) <= y(j) for some j such that 1 <= j < ny (or) !! * z(k+1) <= z(k) for some k such that 1 <= k < nz (or) !! * t(l+1) <= t(l) for some l such that 1 <= l < nt (or) !! * xx(ii+1) < xx(ii) for some ii such that 1 <= ii < mx (or) !! * yy(jj+1) < yy(jj) for some jj such that 1 <= jj < my (or) !! * zz(kk+1) < zz(k) for some kk such that 1 <= kk < mz (or) !! * tt(ll+1) < tt(l) for some ll such that 1 <= ll < mt !! * ier = 5 if lw or liw is too small (insufficient work space) !! * ier = 6 if any of intpol(1),intpol(2),intpol(3),intpol(4) !! is not equal to 1 or 3 integer,intent(inout) :: iw(liw) !! an integer work space of length at least liw !! which must be provided in the routine calling rgrd4 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 = 6). real(wp),intent(in) :: x(nx) !! a real(wp) nx vector of strictly increasing values which defines the x !! portion of the orthogonal grid on which p is given real(wp),intent(in) :: y(ny) !! a real(wp) ny vector of strictly increasing values which defines the y !! portion of the orthogonal grid on which p is given real(wp),intent(in) :: z(nz) !! a real(wp) nz vector of strictly increasing values which defines the z !! portion of the orthogonal grid on which p is given real(wp),intent(in) :: t(nt) !! a real(wp) nt vector of strictly increasing values which defines the t !! portion of the orthogonal grid on which p is given real(wp),intent(in) :: p(nx,ny,nz,nt) !! a real(wp) nx by ny by nz by nt array of values given on the (x,y,z,t) grid real(wp),intent(inout) :: w(lw) !! a real(wp) work space of length at least lw !! which must be provided in the routine calling rgrd4 real(wp),intent(in) :: xx(mx) !! a real(wp) mx vector of increasing values which defines the x portion of the !! orthogonal grid on which q is defined. xx(1) < x(1) or xx(mx) > x(nx) !! is not allowed (see ier = 3) real(wp),intent(in) :: yy(my) !! a real(wp) my vector of increasing values which defines the y portion of the !! orthogonal grid on which q is defined. yy(1) < y(1) or yy(my) > y(ny) !! is not allowed (see ier = 3) real(wp),intent(in) :: zz(mz) !! a real(wp) mz vector of increasing values which defines the z portion of the !! orthogonal grid on which q is defined. zz(1) < z(1) or zz(mz) > z(nz) !! is not allowed (see ier = 3) real(wp),intent(in) :: tt(mt) !! a real(wp) mt vector of increasing values which defines the t portion of the !! orthogonal grid on which q is defined. tt(1) < t(1) or tt(mt) > t(nt) !! is not allowed (see ier = 3) real(wp),intent(out) :: q(mx,my,mz,mt) !! a real(wp) mx by my by mz by mt array of values on the (xx,yy,zz,tt) grid !! which are interpolated from p on the (x,y,z,t) grid integer :: l2,l3,l4,l5,l6,l7,l8,l9 integer :: k2,k3,k4,k5,k6,k7,k8,k9 integer :: j2,j3,j4,j5,j6,j7,j8,j9 integer :: i2,i3,i4,i5 integer :: lwx,lwy,lwz,lwt,mxmy,mxmymz integer :: ii,jj,kk,ll,i,j,k,l integer :: jy,kz,lt ! check input arguments ! check (xx,yy,zz,tt) grid resolution ier = 1 if (min(mx,my,mz,mt) < 1) return ! check intpol ier = 6 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 (x,y,z,t) grid resolution 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 ! check work space length input and set minimum ier = 5 mxmy = mx*my mxmymz = mxmy*mz if (intpol(1)==1) then lwx = mx else lwx = 4*mx end if if (intpol(2)==1) then lwy = (my+2*mx) else lwy = 4*(mx+my) end if if (intpol(3)==1) then lwz = (2*mxmy+mz) else lwz = 4*(mxmy+mz) end if if (intpol(4)==1) then lwt = (2*mxmymz+mt) else lwt = 4*(mxmymz+mt) end if if (lw < lwx+lwy+lwz+lwt) return if (liw < mx+my+mz+mt) return ! check (xx,yy,zz,tt) grid contained in (x,y,z,t) grid ier = 3 if (xx(1)<x(1) .or. xx(mx)>x(nx)) return if (yy(1)<y(1) .or. yy(my)>y(ny)) return if (zz(1)<z(1) .or. zz(mz)>z(nz)) return if (tt(1)<t(1) .or. tt(mt)>t(nt)) return ! check montonicity of grids ier = 4 do i=2,nx if (x(i-1)>=x(i)) return end do do j=2,ny if (y(j-1)>=y(j)) return end do do k=2,nz if (z(k-1)>=z(k)) return end do do l=2,nt if (t(l-1)>=t(l)) return end do do ii=2,mx if (xx(ii-1)>xx(ii)) return end do do jj=2,my if (yy(jj-1)>yy(jj)) return end do do kk=2,mz if (zz(kk-1)>zz(kk)) return end do do ll=2,mt if (tt(ll-1)>tt(ll)) return end do ! arguments o.k. ier = 0 ! set pointers for integer work space iw 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 linmx(nt,t,mt,tt,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 linmx(nz,z,mz,zz,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 cubnmx(nz,z,mz,zz,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 linmx(ny,y,my,yy,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 cubnmx(ny,y,my,yy,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 linmx(nx,x,mx,xx,iw,w(i3)) else ! cubic in x i3 = i2+mx i4 = i3+mx i5 = i4+mx call cubnmx(nx,x,mx,xx,iw,w(i2),w(i3),w(i4),w(i5)) end if ! linearly interpolate in t call lint4(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)) 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 cubnmx(nt,t,mt,tt,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 linmx(nz,z,mz,zz,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 cubnmx(nz,z,mz,zz,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 linmx(ny,y,my,yy,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 cubnmx(ny,y,my,yy,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 linmx(nx,x,mx,xx,iw,w(i3)) else i3 = i2+mx i4 = i3+mx i5 = i4+mx call cubnmx(nx,x,mx,xx,iw,w(i2),w(i3),w(i4),w(i5)) end if ! cubically interpolate in t call cubt4(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)) end if end subroutine rgrd4