1418 CALL this%find_index(in, .false., &
1419 this%innx, this%inny, xmin, xmax, ymin, ymax, &
1420 lout%dim%lon, lout%dim%lat, this%trans%extrap, &
1421 this%inter_index_x, this%inter_index_y)
1423 ALLOCATE(this%inter_x(this%innx,this%inny), &
1424 this%inter_y(this%innx,this%inny))
1425 ALLOCATE(this%inter_xp(this%outnx,this%outny), &
1426 this%inter_yp(this%outnx,this%outny))
1429 CALL griddim_gen_coord(in, this%inter_x, this%inter_y)
1431 CALL proj(in, lout%dim%lon, lout%dim%lat, this%inter_xp, this%inter_yp)
1434 CALL this%find_index(in, .true., &
1435 this%innx, this%inny, xmin, xmax, ymin, ymax, &
1436 lout%dim%lon, lout%dim%lat, this%trans%extrap, &
1437 this%inter_index_x, this%inter_index_y)
1439 IF (this%trans%trans_type ==
'intersearch')
THEN
1440 ALLOCATE(this%inter_x(this%innx,this%inny), &
1441 this%inter_y(this%innx,this%inny))
1442 ALLOCATE(this%inter_xp(this%outnx,this%outny), &
1443 this%inter_yp(this%outnx,this%outny))
1446 CALL griddim_gen_coord(in, this%inter_x, this%inter_y)
1448 CALL proj(in, lout%dim%lon, lout%dim%lat, this%inter_xp, this%inter_yp)
1456ELSE IF (this%trans%trans_type ==
'boxinter')
THEN
1458 CALL outgrid_setup()
1459 CALL get_val(in, nx=this%innx, ny=this%inny)
1460 CALL get_val(out, nx=this%outnx, ny=this%outny, &
1461 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
1464 IF (.NOT.
c_e(this%trans%area_info%boxdx)) &
1465 CALL get_val(out, dx=this%trans%area_info%boxdx)
1466 IF (.NOT.
c_e(this%trans%area_info%boxdy)) &
1467 CALL get_val(out, dx=this%trans%area_info%boxdy)
1469 this%trans%area_info%boxdx = this%trans%area_info%boxdx*0.5d0
1470 this%trans%area_info%boxdy = this%trans%area_info%boxdy*0.5d0
1472 ALLOCATE(this%inter_index_x(this%innx,this%inny), &
1473 this%inter_index_y(this%innx,this%inny))
1479 CALL this%find_index(out, .true., &
1480 this%outnx, this%outny, xmin, xmax, ymin, ymax, &
1481 lin%dim%lon, lin%dim%lat, .false., &
1482 this%inter_index_x, this%inter_index_y)
1487ELSE IF (this%trans%trans_type ==
'stencilinter')
THEN
1489 CALL outgrid_setup()
1491 CALL get_val(in, nx=this%innx, ny=this%inny, &
1492 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
1493 CALL get_val(out, nx=this%outnx, ny=this%outny)
1495 ALLOCATE (this%inter_index_x(this%outnx,this%outny), &
1496 this%inter_index_y(this%outnx,this%outny))
1497 CALL copy(out, lout)
1499 CALL this%find_index(in, .true., &
1500 this%innx, this%inny, xmin, xmax, ymin, ymax, &
1501 lout%dim%lon, lout%dim%lat, this%trans%extrap, &
1502 this%inter_index_x, this%inter_index_y)
1505 nr = int(this%trans%area_info%radius)
1508 r2 = this%trans%area_info%radius**2
1509 ALLOCATE(this%stencil(n,n))
1510 this%stencil(:,:) = .true.
1513 IF ((ix-nm)**2+(iy-nm)**2 > r2) this%stencil(ix,iy) = .false.
1520 xnmax = this%innx - nr
1522 ynmax = this%inny - nr
1523 DO iy = 1, this%outny
1524 DO ix = 1, this%outnx
1525 IF (this%inter_index_x(ix,iy) < xnmin .OR. &
1526 this%inter_index_x(ix,iy) > xnmax .OR. &
1527 this%inter_index_y(ix,iy) < ynmin .OR. &
1528 this%inter_index_y(ix,iy) > ynmax)
THEN
1529 this%inter_index_x(ix,iy) = imiss
1530 this%inter_index_y(ix,iy) = imiss
1537 'stencilinter: stencil size '//t2c(n*n))
1539 'stencilinter: stencil points '//t2c(count(this%stencil)))
1545ELSE IF (this%trans%trans_type ==
'maskgen')
THEN
1547 IF (this%trans%sub_type ==
'poly')
THEN
1550 CALL get_val(in, nx=this%innx, ny=this%inny)
1551 this%outnx = this%innx
1552 this%outny = this%inny
1555 ALLOCATE(this%inter_index_x(this%innx,this%inny), &
1556 this%inter_index_y(this%innx,this%inny))
1557 this%inter_index_x(:,:) = imiss
1558 this%inter_index_y(:,:) = 1
1567 inside_x:
DO i = 1, this%innx
1568 point = georef_coord_new(x=out%dim%lon(i,j), y=out%dim%lat(i,j))
1570 DO n = nprev, this%trans%poly%arraysize
1571 IF (
inside(point, this%trans%poly%array(n)))
THEN
1572 this%inter_index_x(i,j) = n
1577 DO n = nprev-1, 1, -1
1578 IF (
inside(point, this%trans%poly%array(n)))
THEN
1579 this%inter_index_x(i,j) = n
1590 ELSE IF (this%trans%sub_type ==
'grid')
THEN
1593 CALL copy(out, lout)
1596 CALL get_val(in, nx=this%innx, ny=this%inny)
1597 this%outnx = this%innx
1598 this%outny = this%inny
1599 CALL get_val(lout, nx=nx, ny=ny, &
1600 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
1603 ALLOCATE(this%inter_index_x(this%innx,this%inny), &
1604 this%inter_index_y(this%innx,this%inny))
1610 CALL this%find_index(lout, .true., &
1611 nx, ny, xmin, xmax, ymin, ymax, &
1612 out%dim%lon, out%dim%lat, .false., &
1613 this%inter_index_x, this%inter_index_y)
1615 WHERE(
c_e(this%inter_index_x(:,:)))
1616 this%inter_index_x(:,:) = this%inter_index_x(:,:) + &
1617 (this%inter_index_y(:,:)-1)*nx
1625ELSE IF (this%trans%trans_type ==
'polyinter')
THEN
1631 CALL get_val(in, nx=this%innx, ny=this%inny)
1632 this%outnx = this%innx
1633 this%outny = this%inny
1636 ALLOCATE(this%inter_index_x(this%innx,this%inny), &
1637 this%inter_index_y(this%innx,this%inny))
1638 this%inter_index_x(:,:) = imiss
1639 this%inter_index_y(:,:) = 1
1648 inside_x_2:
DO i = 1, this%innx
1649 point = georef_coord_new(x=out%dim%lon(i,j), y=out%dim%lat(i,j))
1651 DO n = nprev, this%trans%poly%arraysize
1652 IF (
inside(point, this%trans%poly%array(n)))
THEN
1653 this%inter_index_x(i,j) = n
1658 DO n = nprev-1, 1, -1
1659 IF (
inside(point, this%trans%poly%array(n)))
THEN
1660 this%inter_index_x(i,j) = n
1673ELSE IF (this%trans%trans_type ==
'metamorphosis')
THEN
1676 CALL get_val(in, nx=this%innx, ny=this%inny)
1677 this%outnx = this%innx
1678 this%outny = this%inny
1680 IF (this%trans%sub_type ==
'maskvalid' .OR. this%trans%sub_type ==
'maskinvalid')
THEN
1682 IF (.NOT.
PRESENT(maskgrid))
THEN
1684 'grid_transform_init maskgrid argument missing for metamorphosis:'// &
1685 trim(this%trans%sub_type)//
' transformation')
1690 IF (this%innx /=
SIZE(maskgrid,1) .OR. this%inny /=
SIZE(maskgrid,2))
THEN
1692 'grid_transform_init mask non conformal with input field')
1694 'mask: '//t2c(
SIZE(maskgrid,1))//
'x'//t2c(
SIZE(maskgrid,2))// &
1695 ' input field:'//t2c(this%innx)//
'x'//t2c(this%inny))
1700 ALLOCATE(this%point_mask(this%innx,this%inny))
1702 IF (this%trans%sub_type ==
'maskvalid')
THEN
1705 IF (.NOT.
PRESENT(maskbounds))
THEN
1706 this%point_mask(:,:) =
c_e(maskgrid(:,:))
1707 ELSE IF (
SIZE(maskbounds) < 2)
THEN
1708 this%point_mask(:,:) =
c_e(maskgrid(:,:))
1710 this%point_mask(:,:) =
c_e(maskgrid(:,:)) .AND. &
1711 maskgrid(:,:) > maskbounds(1) .AND. &
1712 maskgrid(:,:) <= maskbounds(
SIZE(maskbounds))
1715 this%point_mask(:,:) = .NOT.
c_e(maskgrid(:,:))
1720 ELSE IF (this%trans%sub_type ==
'lemaskinvalid' .OR. &
1721 this%trans%sub_type ==
'ltmaskinvalid' .OR. &
1722 this%trans%sub_type ==
'gemaskinvalid' .OR. &
1723 this%trans%sub_type ==
'gtmaskinvalid')
THEN
1726 this%val_mask = maskgrid
1729 ELSE IF (this%trans%sub_type ==
'setinvalidto')
THEN
1731 IF (.NOT.
PRESENT(maskbounds))
THEN
1733 'grid_transform_init maskbounds missing for metamorphosis:'// &
1734 trim(this%trans%sub_type)//
' transformation')
1736 ELSE IF (
SIZE(maskbounds) < 1)
THEN
1738 'grid_transform_init maskbounds empty for metamorphosis:'// &
1739 trim(this%trans%sub_type)//
' transformation')
1742 this%val1 = maskbounds(1)
1745 "grid_transform_init setting invalid data to "//t2c(this%val1))
1751 ELSE IF (this%trans%sub_type ==
'settoinvalid')
THEN
1753 IF (.NOT.
PRESENT(maskbounds))
THEN
1755 'grid_transform_init maskbounds missing for metamorphosis:'// &
1756 trim(this%trans%sub_type)//
' transformation')
1759 ELSE IF (
SIZE(maskbounds) < 2)
THEN
1761 'grid_transform_init maskbounds must have at least 2 elements for metamorphosis:'// &
1762 trim(this%trans%sub_type)//
' transformation')
1766 this%val1 = maskbounds(1)
1767 this%val2 = maskbounds(
SIZE(maskbounds))
1770 "grid_transform_init setting to invalid interval ]"//t2c(this%val1)//
','// &
1771 t2c(this%val2)//
']')
1785SUBROUTINE outgrid_setup()
1788CALL griddim_setsteps(out)
1790CALL get_val(in,
proj=proj_in, component_flag=cf_i)
1791CALL get_val(out,
proj=proj_out, component_flag=cf_o)
1792IF (proj_in == proj_out)
THEN
1795 CALL set_val(out, component_flag=cf_i)
1801 'trying to interpolate a grid with component flag 1 to a grid on a different projection')
1803 'vector fields will probably be wrong')
1805 CALL set_val(out, component_flag=cf_i)
1809CALL griddim_set_central_lon(in, griddim_central_lon(out))
1811END SUBROUTINE outgrid_setup
1813END SUBROUTINE grid_transform_init
1858SUBROUTINE grid_transform_grid_vol7d_init(this, trans, in, v7d_out, &
1859 maskgrid, maskbounds, find_index, categoryappend)
1863TYPE(
vol7d),
INTENT(inout) :: v7d_out
1864REAL,
INTENT(in),
OPTIONAL :: maskgrid(:,:)
1865REAL,
INTENT(in),
OPTIONAL :: maskbounds(:)
1866PROCEDURE(basic_find_index),
POINTER,
OPTIONAL :: find_index
1867CHARACTER(len=*),
INTENT(in),
OPTIONAL :: categoryappend
1869INTEGER :: ix, iy, n, nm, nr, nprev, nmaskarea, xnmin, xnmax, ynmin, ynmax, &
1871DOUBLE PRECISION :: xmin, xmax, ymin, ymax, r2, lonref
1872DOUBLE PRECISION,
ALLOCATABLE :: lon1(:), lat1(:), lon(:,:), lat(:,:)
1873REAL,
ALLOCATABLE :: lmaskbounds(:)
1878IF (
PRESENT(find_index))
THEN
1879 IF (
ASSOCIATED(find_index))
THEN
1880 this%find_index => find_index
1883CALL grid_transform_init_common(this, trans, categoryappend)
1889CALL get_val(trans, time_definition=time_definition)
1890IF (.NOT.
c_e(time_definition))
THEN
1894IF (this%trans%trans_type ==
'inter')
THEN
1896 IF (this%trans%sub_type ==
'near' .OR. this%trans%sub_type ==
'bilin' &
1897 .OR. this%trans%sub_type ==
'shapiro_near')
THEN
1900 CALL get_val(lin, nx=this%innx, ny=this%inny)
1901 this%outnx =
SIZE(v7d_out%ana)
1904 ALLOCATE (this%inter_index_x(this%outnx,this%outny),&
1905 this%inter_index_y(this%outnx,this%outny))
1906 ALLOCATE(lon(this%outnx,1),lat(this%outnx,1))
1908 CALL getval(v7d_out%ana(:)%coord,lon=lon(:,1),lat=lat(:,1))
1910 lonref = 0.5d0*(maxval(lon(:,1), mask=
c_e(lon(:,1))) + minval(lon(:,1), mask=
c_e(lon(:,1))))
1911 CALL griddim_set_central_lon(lin, lonref)
1912 CALL get_val(lin, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
1914 IF (this%trans%sub_type ==
'bilin')
THEN
1915 CALL this%find_index(lin, .false., &
1916 this%innx, this%inny, xmin, xmax, ymin, ymax, &
1917 lon, lat, this%trans%extrap, &
1918 this%inter_index_x, this%inter_index_y)
1920 ALLOCATE(this%inter_x(this%innx,this%inny),this%inter_y(this%innx,this%inny))
1921 ALLOCATE(this%inter_xp(this%outnx,this%outny),this%inter_yp(this%outnx,this%outny))
1923 CALL griddim_gen_coord(lin, this%inter_x, this%inter_y)
1924 CALL proj(lin, lon, lat, this%inter_xp, this%inter_yp)
1927 CALL this%find_index(lin, .true., &
1928 this%innx, this%inny, xmin, xmax, ymin, ymax, &
1929 lon, lat, this%trans%extrap, &
1930 this%inter_index_x, this%inter_index_y)
1932 IF (this%trans%trans_type ==
'intersearch')
THEN
1933 ALLOCATE(this%inter_x(this%innx,this%inny),this%inter_y(this%innx,this%inny))
1934 ALLOCATE(this%inter_xp(this%outnx,this%outny),this%inter_yp(this%outnx,this%outny))
1936 CALL griddim_gen_coord(lin, this%inter_x, this%inter_y)
1937 CALL proj(lin, lon, lat, this%inter_xp, this%inter_yp)
1948ELSE IF (this%trans%trans_type ==
'polyinter')
THEN
1950 CALL get_val(in, nx=this%innx, ny=this%inny)
1952 ALLOCATE(this%inter_index_x(this%innx,this%inny), &
1953 this%inter_index_y(this%innx,this%inny))
1954 this%inter_index_x(:,:) = imiss
1955 this%inter_index_y(:,:) = 1
1961 this%outnx = this%trans%poly%arraysize
1964 CALL init(v7d_out, time_definition=time_definition)
1965 CALL vol7d_alloc(v7d_out, nana=this%outnx)
1968 ALLOCATE(lon(this%outnx,1))
1969 CALL getval(v7d_out%ana(:)%coord,lon=lon(:,1))
1970 lonref = 0.5d0*(maxval(lon(:,1), mask=
c_e(lon(:,1))) + minval(lon(:,1), mask=
c_e(lon(:,1))))
1971 CALL griddim_set_central_lon(lin, lonref)
1976 CALL poly_to_coordinates(this%trans%poly, v7d_out)
1981 DO iy = 1, this%inny
1982 inside_x:
DO ix = 1, this%innx
1983 point = georef_coord_new(x=lin%dim%lon(ix,iy), y=lin%dim%lat(ix,iy))
1985 DO n = nprev, this%trans%poly%arraysize
1986 IF (
inside(point, this%trans%poly%array(n)))
THEN
1987 this%inter_index_x(ix,iy) = n
1992 DO n = nprev-1, 1, -1
1993 IF (
inside(point, this%trans%poly%array(n)))
THEN
1994 this%inter_index_x(ix,iy) = n
2046 this%stencil(:,:) = .true.
2049 IF ((ix-nm)**2+(iy-nm)**2 > r2) this%stencil(ix,iy) = .false.
2056 xnmax = this%innx - nr
2058 ynmax = this%inny - nr
2059 DO iy = 1, this%outny
2060 DO ix = 1, this%outnx
2061 IF (this%inter_index_x(ix,iy) < xnmin .OR. &
2062 this%inter_index_x(ix,iy) > xnmax .OR. &
2063 this%inter_index_y(ix,iy) < ynmin .OR. &
2064 this%inter_index_y(ix,iy) > ynmax)
THEN
2065 this%inter_index_x(ix,iy) = imiss
2066 this%inter_index_y(ix,iy) = imiss
2073 'stencilinter: stencil size '//t2c(n*n))
2075 'stencilinter: stencil points '//t2c(count(this%stencil)))
2083ELSE IF (this%trans%trans_type ==
'maskinter')
THEN
2085 IF (.NOT.
PRESENT(maskgrid))
THEN
2087 'grid_transform_init maskgrid argument missing for maskinter transformation')
2088 CALL raise_fatal_error()
2091 CALL get_val(in, nx=this%innx, ny=this%inny)
2092 IF (this%innx /=
SIZE(maskgrid,1) .OR. this%inny /=
SIZE(maskgrid,2))
THEN
2094 'grid_transform_init mask non conformal with input field')
2096 'mask: '//t2c(
SIZE(maskgrid,1))//
'x'//t2c(
SIZE(maskgrid,2))// &
2097 ' input field:'//t2c(this%innx)//
'x'//t2c(this%inny))
2098 CALL raise_fatal_error()
2101 ALLOCATE(this%inter_index_x(this%innx,this%inny), &
2102 this%inter_index_y(this%innx,this%inny))
2103 this%inter_index_x(:,:) = imiss
2104 this%inter_index_y(:,:) = 1
2107 CALL gen_mask_class()
2115 DO iy = 1, this%inny
2116 DO ix = 1, this%innx
2117 IF (
c_e(maskgrid(ix,iy)))
THEN
2118 IF (maskgrid(ix,iy) <= lmaskbounds(nmaskarea+1))
THEN
2119 DO n = nmaskarea, 1, -1
2120 IF (maskgrid(ix,iy) > lmaskbounds(n))
THEN
2121 this%inter_index_x(ix,iy) = n
2131 this%outnx = nmaskarea
2134 CALL init(v7d_out, time_definition=time_definition)
2135 CALL vol7d_alloc(v7d_out, nana=nmaskarea)
2140 CALL init(v7d_out%ana(n), &
2142 mask=(this%inter_index_x(:,:) == n))), &
2144 mask=(this%inter_index_x(:,:) == n))))
2150ELSE IF (this%trans%trans_type ==
'metamorphosis')
THEN
2157 CALL get_val(in, nx=this%innx, ny=this%inny)
2159 ALLOCATE(this%point_index(this%innx,this%inny))
2160 this%point_index(:,:) = imiss
2162 IF (this%trans%sub_type /=
'index')
THEN
2164 CALL init(v7d_out, time_definition=time_definition)
2167 IF (this%trans%sub_type ==
'all' )
THEN
2169 this%outnx = this%innx*this%inny
2171 CALL vol7d_alloc(v7d_out, nana=this%outnx)
2176 CALL init(v7d_out%ana((iy-1)*this%innx+ix), &
2177 lon=lin%dim%lon(ix,iy),lat=lin%dim%lat(ix,iy))
2179 this%point_index(ix,iy) = n
2185 ELSE IF (this%trans%sub_type ==
'coordbb' )
THEN
2190 DO iy = 1, this%inny
2191 DO ix = 1, this%innx
2193 IF (lin%dim%lon(ix,iy) > this%trans%rect_coo%ilon .AND. &
2194 lin%dim%lon(ix,iy) < this%trans%rect_coo%flon .AND. &
2195 lin%dim%lat(ix,iy) > this%trans%rect_coo%ilat .AND. &
2196 lin%dim%lat(ix,iy) < this%trans%rect_coo%flat)
THEN
2197 this%outnx = this%outnx + 1
2198 this%point_index(ix,iy) = this%outnx
2203 IF (this%outnx <= 0)
THEN
2205 "metamorphosis:coordbb: no points inside bounding box "//&
2206 trim(
to_char(this%trans%rect_coo%ilon))//
","// &
2207 trim(
to_char(this%trans%rect_coo%flon))//
","// &
2208 trim(
to_char(this%trans%rect_coo%ilat))//
","// &
2209 trim(
to_char(this%trans%rect_coo%flat)))
2212 CALL vol7d_alloc(v7d_out, nana=this%outnx)
2216 DO iy = 1, this%inny
2217 DO ix = 1, this%innx
2218 IF (
c_e(this%point_index(ix,iy)))
THEN
2220 CALL init(v7d_out%ana(n), &
2221 lon=lin%dim%lon(ix,iy), lat=lin%dim%lat(ix,iy))
2228 ELSE IF (this%trans%sub_type ==
'poly' )
THEN
2241 DO iy = 1, this%inny
2242 DO ix = 1, this%innx
2243 point = georef_coord_new(x=lin%dim%lon(ix,iy), y=lin%dim%lat(ix,iy))
2244 DO n = 1, this%trans%poly%arraysize
2245 IF (
inside(point, this%trans%poly%array(n)))
THEN
2249 this%outnx = this%outnx + 1
2251 this%point_index(ix,iy) = n
2260 IF (this%outnx <= 0)
THEN
2262 "metamorphosis:poly: no points inside polygons")
2265 CALL vol7d_alloc(v7d_out, nana=this%outnx)
2268 DO iy = 1, this%inny
2269 DO ix = 1, this%innx
2270 IF (
c_e(this%point_index(ix,iy)))
THEN
2272 CALL init(v7d_out%ana(n), &
2273 lon=lin%dim%lon(ix,iy), lat=lin%dim%lat(ix,iy))
2280 ELSE IF (this%trans%sub_type ==
'mask' )
THEN
2282 IF (.NOT.
PRESENT(maskgrid))
THEN
2284 'grid_transform_init maskgrid argument missing for metamorphosis:mask transformation')
2289 IF (this%innx /=
SIZE(maskgrid,1) .OR. this%inny /=
SIZE(maskgrid,2))
THEN
2291 'grid_transform_init mask non conformal with input field')
2293 'mask: '//t2c(
SIZE(maskgrid,1))//
'x'//t2c(
SIZE(maskgrid,2))// &
2294 ' input field:'//t2c(this%innx)//
'x'//t2c(this%inny))
2300 CALL gen_mask_class()
2312 DO iy = 1, this%inny
2313 DO ix = 1, this%innx
2314 IF (
c_e(maskgrid(ix,iy)))
THEN
2315 IF (maskgrid(ix,iy) <= lmaskbounds(nmaskarea+1))
THEN
2316 DO n = nmaskarea, 1, -1
2317 IF (maskgrid(ix,iy) > lmaskbounds(n))
THEN
2321 this%outnx = this%outnx + 1
2323 this%point_index(ix,iy) = n
2334 IF (this%outnx <= 0)
THEN
2336 "grid_transform_init no points inside mask for metamorphosis:mask transformation")
2341 "points in subarea "//t2c(n)//
": "// &
2342 t2c(count(this%point_index(:,:) == n)))
2345 CALL vol7d_alloc(v7d_out, nana=this%outnx)
2348 DO iy = 1, this%inny
2349 DO ix = 1, this%innx
2350 IF (
c_e(this%point_index(ix,iy)))
THEN
2352 CALL init(v7d_out%ana(n),lon=lin%dim%lon(ix,iy),lat=lin%dim%lat(ix,iy))
2359 ELSE IF (this%trans%sub_type ==
'index')
THEN
2360 this%outnx =
SIZE(v7d_out%ana)
2365 IF (any(
c_e(lin%dim%lon)))
THEN
2366 DO n = 1,
SIZE(v7d_out%ana)
2367 iy = (v7d_out%volanai(n,1,1) - 1)/this%innx + 1
2368 ix = v7d_out%volanai(n,1,1) - (iy-1)*this%innx
2369 this%point_index(ix,iy) = v7d_out%volanai(n,1,1)
2370 CALL init(v7d_out%ana(n), &
2371 lon=lin%dim%lon(ix,iy), lat=lin%dim%lat(ix,iy))
2374 DO n = 1,
SIZE(v7d_out%ana)
2375 iy = (v7d_out%volanai(n,1,1) - 1)/this%innx + 1
2376 ix = v7d_out%volanai(n,1,1) - (iy-1)*this%innx
2377 this%point_index(ix,iy) = v7d_out%volanai(n,1,1)
2387SUBROUTINE gen_mask_class()
2388REAL :: startmaskclass, mmin, mmax
2391IF (
PRESENT(maskbounds))
THEN
2392 nmaskarea =
SIZE(maskbounds) - 1
2393 IF (nmaskarea > 0)
THEN
2394 lmaskbounds = maskbounds
2396 ELSE IF (nmaskarea == 0)
THEN
2398 'only one value provided for maskbounds, '//t2c(maskbounds(1)) &
2399 //
', it will be ignored')
2401 'at least 2 values are required for maskbounds')
2405mmin = minval(maskgrid, mask=
c_e(maskgrid))
2406mmax = maxval(maskgrid, mask=
c_e(maskgrid))
2408nmaskarea = int(mmax - mmin + 1.5)
2409startmaskclass = mmin - 0.5
2411ALLOCATE(lmaskbounds(nmaskarea+1))
2412lmaskbounds(:) = (/(startmaskclass+real(i),i=0,nmaskarea)/)
2415 'maskinter, '//t2c(nmaskarea)//
' subareas defined, with boundaries:')
2416DO i = 1,
SIZE(lmaskbounds)
2418 'maskinter '//t2c(i)//
' '//t2c(lmaskbounds(i)))
2422END SUBROUTINE gen_mask_class
2424END SUBROUTINE grid_transform_grid_vol7d_init
2445SUBROUTINE grid_transform_vol7d_grid_init(this, trans, v7d_in, out, categoryappend)
2448TYPE(
vol7d),
INTENT(in) :: v7d_in
2450character(len=*),
INTENT(in),
OPTIONAL :: categoryappend
2453DOUBLE PRECISION :: xmin, xmax, ymin, ymax, lonref
2454DOUBLE PRECISION,
ALLOCATABLE :: lon(:,:),lat(:,:)
2458CALL grid_transform_init_common(this, trans, categoryappend)
2463IF (this%trans%trans_type ==
'inter')
THEN
2465 IF ( this%trans%sub_type ==
'linear' )
THEN
2467 this%innx=
SIZE(v7d_in%ana)
2469 ALLOCATE(lon(this%innx,1),lat(this%innx,1))
2470 ALLOCATE(this%inter_xp(this%innx,this%inny),this%inter_yp(this%innx,this%inny))
2471 CALL getval(v7d_in%ana(:)%coord,lon=lon(:,1),lat=lat(:,1))
2473 CALL copy (out, lout)
2475 lonref = 0.5d0*(maxval(lon(:,1), mask=
c_e(lon(:,1))) + minval(lon(:,1), mask=
c_e(lon(:,1))))
2476 CALL griddim_set_central_lon(lout, lonref)
2478 CALL get_val(lout, nx=nx, ny=ny)
2481 ALLOCATE(this%inter_x(this%outnx,this%outny),this%inter_y(this%outnx,this%outny))
2483 CALL get_val(lout, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
2484 CALL proj(lout, lon, lat, this%inter_xp, this%inter_yp)
2485 CALL griddim_gen_coord(lout, this%inter_x, this%inter_y)
2494ELSE IF (this%trans%trans_type ==
'boxinter')
THEN
2496 this%innx=
SIZE(v7d_in%ana)
2499 ALLOCATE(lon(this%innx,1),lat(this%innx,1))
2500 ALLOCATE(this%inter_index_x(this%innx,this%inny), &
2501 this%inter_index_y(this%innx,this%inny))
2503 CALL getval(v7d_in%ana(:)%coord,lon=lon(:,1),lat=lat(:,1))
2505 CALL copy (out, lout)
2507 lonref = 0.5d0*(maxval(lon(:,1), mask=
c_e(lon(:,1))) + minval(lon(:,1), mask=
c_e(lon(:,1))))
2508 CALL griddim_set_central_lon(lout, lonref)
2510 CALL get_val(lout, nx=this%outnx, ny=this%outny, &
2511 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
2514 IF (.NOT.
c_e(this%trans%area_info%boxdx)) &
2515 CALL get_val(out, dx=this%trans%area_info%boxdx)
2516 IF (.NOT.
c_e(this%trans%area_info%boxdy)) &
2517 CALL get_val(out, dx=this%trans%area_info%boxdy)
2519 this%trans%area_info%boxdx = this%trans%area_info%boxdx*0.5d0
2520 this%trans%area_info%boxdy = this%trans%area_info%boxdy*0.5d0
2523 CALL this%find_index(lout, .true., &
2524 this%outnx, this%outny, xmin, xmax, ymin, ymax, &
2525 lon, lat, .false., &
2526 this%inter_index_x, this%inter_index_y)
2535END SUBROUTINE grid_transform_vol7d_grid_init
2572SUBROUTINE grid_transform_vol7d_vol7d_init(this, trans, v7d_in, v7d_out, &
2573 maskbounds, categoryappend)
2576TYPE(
vol7d),
INTENT(in) :: v7d_in
2577TYPE(
vol7d),
INTENT(inout) :: v7d_out
2578REAL,
INTENT(in),
OPTIONAL :: maskbounds(:)
2579CHARACTER(len=*),
INTENT(in),
OPTIONAL :: categoryappend
2582DOUBLE PRECISION,
ALLOCATABLE :: lon(:), lat(:)
2584DOUBLE PRECISION :: lon1, lat1
2588CALL grid_transform_init_common(this, trans, categoryappend)
2593IF (this%trans%trans_type ==
'inter')
THEN
2595 IF ( this%trans%sub_type ==
'linear' )
THEN
2597 CALL vol7d_alloc_vol(v7d_out)
2598 this%outnx=
SIZE(v7d_out%ana)
2601 this%innx=
SIZE(v7d_in%ana)
2604 ALLOCATE(this%inter_xp(this%innx,this%inny),this%inter_yp(this%innx,this%inny))
3145 DO i = 1, this%innx - this%trans%box_info%npx + 1, this%trans%box_info%npx
3146 ie = i+this%trans%box_info%npx-1
3148 navg = count(field_in(i:ie,j:je,k) /= rmiss)
3150 field_out(ii,jj,k) = sum(field_in(i:ie,j:je,k), &
3151 mask=(field_in(i:ie,j:je,k) /= rmiss))/navg
3159 ELSE IF (this%trans%sub_type ==
'stddev' .OR. &
3160 this%trans%sub_type ==
'stddevnm1')
THEN
3162 IF (this%trans%sub_type ==
'stddev')
THEN
3168 navg = this%trans%box_info%npx*this%trans%box_info%npy
3170 IF (.NOT.lzlist(k)) cycle
3172 DO j = 1, this%inny - this%trans%box_info%npy + 1, this%trans%box_info%npy
3173 je = j+this%trans%box_info%npy-1
3176 DO i = 1, this%innx - this%trans%box_info%npx + 1, this%trans%box_info%npx
3177 ie = i+this%trans%box_info%npx-1
3180 reshape(field_in(i:ie,j:je,k),(/navg/)), nm1=nm1)
3185 ELSE IF (this%trans%sub_type ==
'max')
THEN
3187 IF (.NOT.lzlist(k)) cycle
3189 DO j = 1, this%inny - this%trans%box_info%npy + 1, this%trans%box_info%npy
3190 je = j+this%trans%box_info%npy-1
3193 DO i = 1, this%innx - this%trans%box_info%npx + 1, this%trans%box_info%npx
3194 ie = i+this%trans%box_info%npx-1
3196 navg = count(field_in(i:ie,j:je,k) /= rmiss)
3198 field_out(ii,jj,k) = maxval(field_in(i:ie,j:je,k), &
3199 mask=(field_in(i:ie,j:je,k) /= rmiss))
3205 ELSE IF (this%trans%sub_type ==
'min')
THEN
3207 IF (.NOT.lzlist(k)) cycle
3209 DO j = 1, this%inny - this%trans%box_info%npy + 1, this%trans%box_info%npy
3210 je = j+this%trans%box_info%npy-1
3213 DO i = 1, this%innx - this%trans%box_info%npx + 1, this%trans%box_info%npx
3214 ie = i+this%trans%box_info%npx-1
3216 navg = count(field_in(i:ie,j:je,k) /= rmiss)
3218 field_out(ii,jj,k) = minval(field_in(i:ie,j:je,k), &
3219 mask=(field_in(i:ie,j:je,k) /= rmiss))
3225 ELSE IF (this%trans%sub_type ==
'percentile')
THEN
3227 navg = this%trans%box_info%npx*this%trans%box_info%npy
3229 IF (.NOT.lzlist(k)) cycle
3231 DO j = 1, this%inny - this%trans%box_info%npy + 1, this%trans%box_info%npy
3232 je = j+this%trans%box_info%npy-1
3235 DO i = 1, this%innx - this%trans%box_info%npx + 1, this%trans%box_info%npx
3236 ie = i+this%trans%box_info%npx-1
3239 reshape(field_in(i:ie,j:je,k),(/navg/)), &
3240 (/real(this%trans%stat_info%percentile)/))
3245 ELSE IF (this%trans%sub_type ==
'frequency')
THEN
3248 IF (.NOT.lzlist(k)) cycle
3250 DO j = 1, this%inny - this%trans%box_info%npy + 1, this%trans%box_info%npy
3251 je = j+this%trans%box_info%npy-1
3254 DO i = 1, this%innx - this%trans%box_info%npx + 1, this%trans%box_info%npx
3255 ie = i+this%trans%box_info%npx-1
3257 navg = count(field_in(i:ie,j:je,k) /= rmiss)
3259 field_out(ii,jj,k) = sum(interval_info_valid( &
3260 this%trans%interval_info, field_in(i:ie,j:je,k)), &
3261 mask=(field_in(i:ie,j:je,k) /= rmiss))/navg
3269ELSE IF (this%trans%trans_type ==
'inter')
THEN
3271 IF (this%trans%sub_type ==
'near')
THEN
3274 IF (.NOT.lzlist(k)) cycle
3275 DO j = 1, this%outny
3276 DO i = 1, this%outnx
3278 IF (
c_e(this%inter_index_x(i,j))) field_out(i,j,k) = &
3279 field_in(this%inter_index_x(i,j),this%inter_index_y(i,j),k)
3285 ELSE IF (this%trans%sub_type ==
'bilin')
THEN
3288 IF (.NOT.lzlist(k)) cycle
3289 DO j = 1, this%outny
3290 DO i = 1, this%outnx
3292 IF (
c_e(this%inter_index_x(i,j)))
THEN
3294 z1=field_in(this%inter_index_x(i,j),this%inter_index_y(i,j),k)
3295 z2=field_in(this%inter_index_x(i,j)+1,this%inter_index_y(i,j),k)
3296 z3=field_in(this%inter_index_x(i,j)+1,this%inter_index_y(i,j)+1,k)
3297 z4=field_in(this%inter_index_x(i,j),this%inter_index_y(i,j)+1,k)
3299 IF (
c_e(z1) .AND.
c_e(z2) .AND.
c_e(z3) .AND.
c_e(z4))
THEN
3301 x1=this%inter_x(this%inter_index_x(i,j),this%inter_index_y(i,j))
3302 y1=this%inter_y(this%inter_index_x(i,j),this%inter_index_y(i,j))
3303 x3=this%inter_x(this%inter_index_x(i,j)+1,this%inter_index_y(i,j)+1)
3304 y3=this%inter_y(this%inter_index_x(i,j)+1,this%inter_index_y(i,j)+1)
3306 xp=this%inter_xp(i,j)
3307 yp=this%inter_yp(i,j)
3309 field_out(i,j,k) = hbilin(z1,z2,z3,z4,x1,y1,x3,y3,xp,yp)
3317 ELSE IF (this%trans%sub_type ==
'shapiro_near')
THEN
3319 IF (.NOT.lzlist(k)) cycle
3320 DO j = 1, this%outny
3321 DO i = 1, this%outnx
3323 IF (
c_e(this%inter_index_x(i,j)))
THEN
3325 IF(this%inter_index_x(i,j)-1>0)
THEN
3326 z(1) = field_in(this%inter_index_x(i,j)-1,this%inter_index_y(i,j) ,k)
3330 IF(this%inter_index_x(i,j)+1<=this%outnx)
THEN
3331 z(3)=field_in(this%inter_index_x(i,j)+1,this%inter_index_y(i,j) ,k)
3335 IF(this%inter_index_y(i,j)+1<=this%outny)
THEN
3336 z(2)=field_in(this%inter_index_x(i,j) ,this%inter_index_y(i,j)+1,k)
3340 IF(this%inter_index_y(i,j)-1>0)
THEN
3341 z(4)=field_in(this%inter_index_x(i,j), this%inter_index_y(i,j)-1,k)
3345 field_out(i,j,k) = shapiro(z,field_in(this%inter_index_x(i,j),this%inter_index_y(i,j),k))
3354ELSE IF (this%trans%trans_type ==
'intersearch')
THEN
3357 likethis%trans%trans_type =
'inter'
3358 CALL grid_transform_compute(likethis, field_in, field_out, var, coord_3d_in, zlist)
3359 CALL getenv(
'LIBSIM_DISABLEOPTSEARCH', env_var)
3360 optsearch = len_trim(env_var) == 0
3363 IF (.NOT.lzlist(k)) cycle
3364 IF ((.NOT.all(
c_e(field_out(:,:,k)))) .AND. (any(
c_e(field_in(:,:,k)))))
THEN
3365 DO j = 1, this%outny
3366 DO i = 1, this%outnx
3367 IF (.NOT.
c_e(field_out(i,j,k)))
THEN
3371 ix = this%inter_index_x(i,j)
3372 iy = this%inter_index_y(i,j)
3373 DO s = 0, max(this%innx, this%inny)
3375 DO m = iy-s, iy+s, max(2*s, 1)
3376 IF (m < 1 .OR. m > this%inny) cycle
3377 DO l = max(1, ix-s), min(this%innx, ix+s)
3378 disttmp = (this%inter_xp(i,j) - this%inter_x(l,m))**2 + (this%inter_yp(i,j) - this%inter_y(l,m))**2
3379 IF (
c_e(field_in(l,m,k)))
THEN
3380 IF (disttmp <
dist)
THEN
3382 field_out(i,j,k) = field_in(l,m,k)
3384 ELSE IF (disttmp ==
dist)
THEN
3385 field_out(i,j,k) = field_out(i,j,k) + field_in(l,m,k)
3386 nearcount = nearcount + 1
3389 IF (disttmp <
dist) farenough = .false.
3392 DO m = max(1, iy-s+1), min(this%inny, iy+s-1)
3393 DO l = ix-s, ix+s, 2*s
3394 IF (l < 1 .OR. l > this%innx) cycle
3395 disttmp = (this%inter_xp(i,j) - this%inter_x(l,m))**2 + (this%inter_yp(i,j) - this%inter_y(l,m))**2
3396 IF (
c_e(field_in(l,m,k)))
THEN
3397 IF (disttmp <
dist)
THEN
3399 field_out(i,j,k) = field_in(l,m,k)
3401 ELSE IF (disttmp ==
dist)
THEN
3402 field_out(i,j,k) = field_out(i,j,k) + field_in(l,m,k)
3403 nearcount = nearcount + 1
3406 IF (disttmp <
dist) farenough = .false.
3409 IF (s > 0 .AND. farenough)
EXIT
3414 IF (
c_e(field_in(l,m,k)))
THEN
3415 disttmp = (this%inter_xp(i,j) - this%inter_x(l,m))**2 + (this%inter_yp(i,j) - this%inter_y(l,m))**2
3416 IF (disttmp <
dist)
THEN
3418 field_out(i,j,k) = field_in(l,m,k)
3420 ELSE IF (disttmp ==
dist)
THEN
3421 field_out(i,j,k) = field_out(i,j,k) + field_in(l,m,k)
3422 nearcount = nearcount + 1
3429 IF (nearcount > 1) field_out(i,j,k) = field_out(i,j,k)/nearcount
3436ELSE IF (this%trans%trans_type ==
'boxinter' &
3437 .OR. this%trans%trans_type ==
'polyinter' &
3438 .OR. this%trans%trans_type ==
'maskinter')
THEN
3440 IF (this%trans%sub_type ==
'average')
THEN
3442 IF (vartype == var_dir360)
THEN
3444 IF (.NOT.lzlist(k)) cycle
3445 DO j = 1, this%outny
3446 DO i = 1, this%outnx
3447 field_out(i,j,k) = find_prevailing_direction(field_in(:,:,k), &
3449 mask=this%inter_index_x(:,:) == i .AND. this%inter_index_y(:,:) == j)
3455 ALLOCATE(nval(this%outnx, this%outny))
3456 field_out(:,:,:) = 0.0
3458 IF (.NOT.lzlist(k)) cycle
3462 IF (
c_e(this%inter_index_x(i,j)) .AND.
c_e(field_in(i,j,k)))
THEN
3463 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) = &
3464 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) + &
3466 nval(this%inter_index_x(i,j),this%inter_index_y(i,j)) = &
3467 nval(this%inter_index_x(i,j),this%inter_index_y(i,j)) + 1
3471 WHERE (nval(:,:) /= 0)
3472 field_out(:,:,k) = field_out(:,:,k)/nval(:,:)
3474 field_out(:,:,k) = rmiss
3480 ELSE IF (this%trans%sub_type ==
'stddev' .OR. &
3481 this%trans%sub_type ==
'stddevnm1')
THEN
3483 IF (this%trans%sub_type ==
'stddev')
THEN
3489 IF (.NOT.lzlist(k)) cycle
3490 DO j = 1, this%outny
3491 DO i = 1, this%outnx
3494 reshape(field_in(:,:,k), (/
SIZE(field_in(:,:,k))/)), &
3495 mask=reshape((this%inter_index_x == i .AND. &
3496 this%inter_index_y == j), (/
SIZE(field_in(:,:,k))/)), nm1=nm1)
3501 ELSE IF (this%trans%sub_type ==
'max')
THEN
3504 IF (.NOT.lzlist(k)) cycle
3507 IF (
c_e(this%inter_index_x(i,j)) .AND.
c_e(field_in(i,j,k)))
THEN
3508 IF (
c_e(field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k)))
THEN
3509 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) = &
3510 max(field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k), &
3513 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) = &
3522 ELSE IF (this%trans%sub_type ==
'min')
THEN
3525 IF (.NOT.lzlist(k)) cycle
3528 IF (
c_e(this%inter_index_x(i,j)) .AND.
c_e(field_in(i,j,k)))
THEN
3529 IF (
c_e(field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k)))
THEN
3530 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) = &
3531 min(field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k), &
3534 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) = &
3542 ELSE IF (this%trans%sub_type ==
'percentile')
THEN
3545 IF (.NOT.lzlist(k)) cycle
3546 DO j = 1, this%outny
3547 DO i = 1, this%outnx
3550 reshape(field_in(:,:,k), (/
SIZE(field_in(:,:,k))/)), &
3551 (/real(this%trans%stat_info%percentile)/), &
3552 mask=reshape((this%inter_index_x == i .AND. &
3553 this%inter_index_y == j), (/
SIZE(field_in(:,:,k))/)))
3558 ELSE IF (this%trans%sub_type ==
'frequency')
THEN
3560 ALLOCATE(nval(this%outnx, this%outny))
3562 IF (.NOT.lzlist(k)) cycle
3563 field_out(:,:,k) = 0.0
3567 IF (
c_e(this%inter_index_x(i,j)) .AND.
c_e(field_in(i,j,k)))
THEN
3568 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) = &
3569 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) + &
3570 interval_info_valid(this%trans%interval_info, field_in(i,j,k))
3571 nval(this%inter_index_x(i,j),this%inter_index_y(i,j)) = &
3572 nval(this%inter_index_x(i,j),this%inter_index_y(i,j)) + 1
3576 WHERE (nval(:,:) /= 0)
3577 field_out(:,:,k) = field_out(:,:,k)/nval(:,:)
3579 field_out(:,:,k) = rmiss
3586ELSE IF (this%trans%trans_type ==
'stencilinter')
THEN
3587 np =
SIZE(this%stencil,1)/2
3588 ns =
SIZE(this%stencil)
3590 IF (this%trans%sub_type ==
'average')
THEN
3592 IF (vartype == var_dir360)
THEN
3594 IF (.NOT.lzlist(k)) cycle
3595 DO j = 1, this%outny
3596 DO i = 1, this%outnx
3597 IF (
c_e(this%inter_index_x(i,j)))
THEN
3598 i1 = this%inter_index_x(i,j) - np
3599 i2 = this%inter_index_x(i,j) + np
3600 j1 = this%inter_index_y(i,j) - np
3601 j2 = this%inter_index_y(i,j) + np
3602 field_out(i,j,k) = find_prevailing_direction(field_in(i1:i2,j1:j2,k), &
3604 mask=this%stencil(:,:))
3615 IF (.NOT.lzlist(k)) cycle
3616 DO j = 1, this%outny
3617 DO i = 1, this%outnx
3618 IF (
c_e(this%inter_index_x(i,j)))
THEN
3619 i1 = this%inter_index_x(i,j) - np
3620 i2 = this%inter_index_x(i,j) + np
3621 j1 = this%inter_index_y(i,j) - np
3622 j2 = this%inter_index_y(i,j) + np
3623 n = count(field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))
3625 field_out(i,j,k) = sum(field_in(i1:i2,j1:j2,k), &
3626 mask=field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))/n
3635 ELSE IF (this%trans%sub_type ==
'stddev' .OR. &
3636 this%trans%sub_type ==
'stddevnm1')
THEN
3638 IF (this%trans%sub_type ==
'stddev')
THEN
3647 IF (.NOT.lzlist(k)) cycle
3648 DO j = 1, this%outny
3649 DO i = 1, this%outnx
3650 IF (
c_e(this%inter_index_x(i,j)))
THEN
3651 i1 = this%inter_index_x(i,j) - np
3652 i2 = this%inter_index_x(i,j) + np
3653 j1 = this%inter_index_y(i,j) - np
3654 j2 = this%inter_index_y(i,j) + np
3657 reshape(field_in(i1:i2,j1:j2,k), (/ns/)), &
3658 mask=reshape(field_in(i1:i2,j1:j2,k) /= rmiss .AND. &
3659 this%stencil(:,:), (/ns/)), nm1=nm1)
3666 ELSE IF (this%trans%sub_type ==
'max')
THEN
3671 IF (.NOT.lzlist(k)) cycle
3672 DO j = 1, this%outny
3673 DO i = 1, this%outnx
3674 IF (
c_e(this%inter_index_x(i,j)))
THEN
3675 i1 = this%inter_index_x(i,j) - np
3676 i2 = this%inter_index_x(i,j) + np
3677 j1 = this%inter_index_y(i,j) - np
3678 j2 = this%inter_index_y(i,j) + np
3679 n = count(field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))
3681 field_out(i,j,k) = maxval(field_in(i1:i2,j1:j2,k), &
3682 mask=field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))
3690 ELSE IF (this%trans%sub_type ==
'min')
THEN
3695 IF (.NOT.lzlist(k)) cycle
3696 DO j = 1, this%outny
3697 DO i = 1, this%outnx
3698 IF (
c_e(this%inter_index_x(i,j)))
THEN
3699 i1 = this%inter_index_x(i,j) - np
3700 i2 = this%inter_index_x(i,j) + np
3701 j1 = this%inter_index_y(i,j) - np
3702 j2 = this%inter_index_y(i,j) + np
3703 n = count(field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))
3705 field_out(i,j,k) = minval(field_in(i1:i2,j1:j2,k), &
3706 mask=field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))
3714 ELSE IF (this%trans%sub_type ==
'percentile')
THEN
3719 IF (.NOT.lzlist(k)) cycle
3720 DO j = 1, this%outny
3721 DO i = 1, this%outnx
3722 IF (
c_e(this%inter_index_x(i,j)))
THEN
3723 i1 = this%inter_index_x(i,j) - np
3724 i2 = this%inter_index_x(i,j) + np
3725 j1 = this%inter_index_y(i,j) - np
3726 j2 = this%inter_index_y(i,j) + np
3729 reshape(field_in(i1:i2,j1:j2,k), (/ns/)), &
3730 (/real(this%trans%stat_info%percentile)/), &
3731 mask=reshape(field_in(i1:i2,j1:j2,k) /= rmiss .AND. &
3732 this%stencil(:,:), (/ns/)))
3739 ELSE IF (this%trans%sub_type ==
'frequency')
THEN
3744 IF (.NOT.lzlist(k)) cycle
3745 DO j = 1, this%outny
3746 DO i = 1, this%outnx
3747 IF (
c_e(this%inter_index_x(i,j)))
THEN
3748 i1 = this%inter_index_x(i,j) - np
3749 i2 = this%inter_index_x(i,j) + np
3750 j1 = this%inter_index_y(i,j) - np
3751 j2 = this%inter_index_y(i,j) + np
3752 n = count(field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))
3754 field_out(i,j,k) = sum(interval_info_valid( &
3755 this%trans%interval_info, field_in(i1:i2,j1:j2,k)), &
3756 mask=field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))/n
3766ELSE IF (this%trans%trans_type ==
'maskgen')
THEN
3769 WHERE(
c_e(this%inter_index_x(:,:)))
3770 field_out(:,:,k) = real(this%inter_index_x(:,:))
3774ELSE IF (this%trans%trans_type ==
'metamorphosis')
THEN
3776 IF (this%trans%sub_type ==
'all')
THEN
3778 field_out(:,:,:) = reshape(field_in(:,:,:), (/this%outnx,this%outny,innz/))
3780 ELSE IF (this%trans%sub_type ==
'coordbb' .OR. this%trans%sub_type ==
'poly' &
3781 .OR. this%trans%sub_type ==
'mask' .OR. this%trans%sub_type ==
'index')
THEN
3784 IF (.NOT.lzlist(k)) cycle
3786 field_out(:,1,k) = pack(field_in(:,:,k),
c_e(this%point_index(:,:)))
3789 ELSE IF (this%trans%sub_type ==
'maskvalid' .OR. &
3790 this%trans%sub_type ==
'maskinvalid')
THEN
3793 IF (.NOT.lzlist(k)) cycle
3794 WHERE (this%point_mask(:,:))
3795 field_out(:,:,k) = field_in(:,:,k)
3799 ELSE IF (this%trans%sub_type ==
'lemaskinvalid')
THEN
3802 IF (.NOT.lzlist(k)) cycle
3803 WHERE (
c_e(field_in(:,:,k)) .AND. field_in(:,:,k) > this%val_mask(:,:))
3804 field_out(:,:,k) = field_in(:,:,k)
3806 field_out(:,:,k) = rmiss
3810 ELSE IF (this%trans%sub_type ==
'ltmaskinvalid')
THEN
3813 IF (.NOT.lzlist(k)) cycle
3814 WHERE (
c_e(field_in(:,:,k)) .AND. field_in(:,:,k) >= this%val_mask(:,:))
3815 field_out(:,:,k) = field_in(:,:,k)
3817 field_out(:,:,k) = rmiss
3821 ELSE IF (this%trans%sub_type ==
'gemaskinvalid')
THEN
3824 IF (.NOT.lzlist(k)) cycle
3825 WHERE (
c_e(field_in(:,:,k)) .AND. field_in(:,:,k) < this%val_mask(:,:))
3826 field_out(:,:,k) = field_in(:,:,k)
3828 field_out(:,:,k) = rmiss
3832 ELSE IF (this%trans%sub_type ==
'gtmaskinvalid')
THEN
3835 IF (.NOT.lzlist(k)) cycle
3836 WHERE (
c_e(field_in(:,:,k)) .AND. field_in(:,:,k) <= this%val_mask(:,:))
3837 field_out(:,:,k) = field_in(:,:,k)
3839 field_out(:,:,k) = rmiss
3843 ELSE IF (this%trans%sub_type ==
'setinvalidto')
THEN
3846 IF (.NOT.lzlist(k)) cycle
3847 WHERE (
c_e(field_in(:,:,k)))
3848 field_out(:,:,k) = field_in(:,:,k)
3850 field_out(:,:,k) = this%val1
3854 ELSE IF (this%trans%sub_type ==
'settoinvalid')
THEN
3855 IF (
c_e(this%val1) .AND.
c_e(this%val2))
THEN
3856 WHERE (
c_e(field_in(:,:,:)) .AND. field_in(:,:,:) > this%val1 &
3857 .AND. field_in(:,:,:) <= this%val2)
3858 field_out(:,:,:) = rmiss
3860 field_out(:,:,:) = field_in(:,:,:)
3862 ELSE IF (
c_e(this%val1))
THEN
3863 WHERE (
c_e(field_in(:,:,:)) .AND. field_in(:,:,:) > this%val1)
3864 field_out(:,:,:) = rmiss
3866 field_out(:,:,:) = field_in(:,:,:)
3868 ELSE IF (
c_e(this%val2))
THEN
3869 WHERE (
c_e(field_in(:,:,:)) .AND. field_in(:,:,:) <= this%val2)
3870 field_out(:,:,:) = rmiss
3872 field_out(:,:,:) = field_in(:,:,:)
3877ELSE IF (this%trans%trans_type ==
'vertint')
THEN
3879 IF (this%trans%sub_type ==
'linear')
THEN
3881 alloc_coord_3d_in_act = .false.
3882 IF (
ASSOCIATED(this%inter_index_z))
THEN
3885 IF (
c_e(this%inter_index_z(k)))
THEN
3886 z1 = real(this%inter_zp(k))
3887 z2 = real(1.0d0 - this%inter_zp(k))
3888 SELECT CASE(vartype)
3893 IF (
c_e(field_in(i,j,this%inter_index_z(k))) .AND. &
3894 c_e(field_in(i,j,this%inter_index_z(k)+1)))
THEN
3895 field_out(i,j,k) = &
3896 interp_var_360(field_in(i,j,this%inter_index_z(k)), &
3897 field_in(i,j,this%inter_index_z(k)+1), z1, z2)
3905 IF (
c_e(field_in(i,j,this%inter_index_z(k))) .AND. &
3906 c_e(field_in(i,j,this%inter_index_z(k)+1)) .AND. &
3907 field_in(i,j,this%inter_index_z(k)) > 0. .AND. &
3908 field_in(i,j,this%inter_index_z(k)+1) > 0.)
THEN
3909 field_out(i,j,k) = exp( &
3910 log(field_in(i,j,this%inter_index_z(k)))*z2 + &
3911 log(field_in(i,j,this%inter_index_z(k)+1))*z1)
3919 IF (
c_e(field_in(i,j,this%inter_index_z(k))) .AND. &
3920 c_e(field_in(i,j,this%inter_index_z(k)+1)))
THEN
3921 field_out(i,j,k) = &
3922 field_in(i,j,this%inter_index_z(k))*z2 + &
3923 field_in(i,j,this%inter_index_z(k)+1)*z1
3935 IF (
ALLOCATED(this%coord_3d_in))
THEN
3936 coord_3d_in_act => this%coord_3d_in
3939 "Using external vertical coordinate for vertint")
3942 IF (
PRESENT(coord_3d_in))
THEN
3945 "Using internal vertical coordinate for vertint")
3947 IF (this%dolog)
THEN
3948 ALLOCATE(coord_3d_in_act(
SIZE(coord_3d_in,1), &
3949 SIZE(coord_3d_in,2),
SIZE(coord_3d_in,3)))
3950 alloc_coord_3d_in_act = .true.
3951 WHERE (
c_e(coord_3d_in) .AND. coord_3d_in > 0.0)
3952 coord_3d_in_act = log(coord_3d_in)
3954 coord_3d_in_act = rmiss
3957 coord_3d_in_act => coord_3d_in
3961 "Missing internal and external vertical coordinate for vertint")
3967 inused =
SIZE(coord_3d_in_act,3)
3968 IF (inused < 2)
RETURN
3972 IF (.NOT.
c_e(this%vcoord_out(k))) cycle
3976 DO kk = 1, max(inused-kkcache-1, kkcache)
3978 kkdown = kkcache - kk + 1
3980 IF (kkdown >= 1)
THEN
3981 IF (this%vcoord_out(k) >= &
3982 min(coord_3d_in_act(i,j,kkdown), coord_3d_in_act(i,j,kkdown+1)) .AND. &
3983 this%vcoord_out(k) < &
3984 max(coord_3d_in_act(i,j,kkdown), coord_3d_in_act(i,j,kkdown+1)))
THEN
3987 kfound = kkcache + this%levshift
3991 IF (kkup < inused)
THEN
3992 IF (this%vcoord_out(k) >= &
3993 min(coord_3d_in_act(i,j,kkup), coord_3d_in_act(i,j,kkup+1)) .AND. &
3994 this%vcoord_out(k) < &
3995 max(coord_3d_in_act(i,j,kkup), coord_3d_in_act(i,j,kkup+1)))
THEN
3998 kfound = kkcache + this%levshift
4005 IF (
c_e(kfound))
THEN
4006 IF (
c_e(field_in(i,j,kfound)) .AND.
c_e(field_in(i,j,kfound+1)))
THEN
4007 z1 = real((this%vcoord_out(k) - coord_3d_in_act(i,j,kfoundin))/ &
4008 (coord_3d_in_act(i,j,kfoundin+1) - coord_3d_in_act(i,j,kfoundin)))
4010 SELECT CASE(vartype)
4013 field_out(i,j,k) = &
4014 interp_var_360(field_in(i,j,kfound), field_in(i,j,kfound+1), z1, z2)
4016 field_out(i,j,k) = exp(log(field_in(i,j,kfound))*z2 + &
4017 log(field_in(i,j,kfound+1))*z1)
4020 field_out(i,j,k) = field_in(i,j,kfound)*z2 + field_in(i,j,kfound+1)*z1
4029 IF (alloc_coord_3d_in_act)
DEALLOCATE(coord_3d_in_act)
4032 ELSE IF (this%trans%sub_type ==
'linearsparse')
THEN
4035 IF (.NOT.
ASSOCIATED(this%vcoord_in) .AND. .NOT.
PRESENT(coord_3d_in))
THEN
4037 "linearsparse interpolation, no input vert coord available")
4041 ALLOCATE(coord_in(innz),val_in(innz),mask_in(innz))
4045 IF (
ASSOCIATED(this%vcoord_in))
THEN
4046 mask_in =
c_e(field_in(i,j,this%levshift+1:this%levshift+this%levused)) &
4047 .AND.
c_e(this%vcoord_in(:))
4049 mask_in =
c_e(field_in(i,j,this%levshift+1:this%levshift+this%levused)) &
4050 .AND.
c_e(coord_3d_in(i,j,:))
4053 IF (vartype == var_press)
THEN
4054 mask_in(:) = mask_in(:) .AND. &
4055 (field_in(i,j,this%levshift+1:this%levshift+this%levused) > 0.0d0)
4057 inused = count(mask_in)
4058 IF (inused > 1)
THEN
4059 IF (
ASSOCIATED(this%vcoord_in))
THEN
4060 coord_in(1:inused) = pack(this%vcoord_in(:), mask=mask_in)
4062 coord_in(1:inused) = pack(coord_3d_in(i,j,:), mask=mask_in)
4064 IF (vartype == var_press)
THEN
4065 val_in(1:inused) = log(pack( &
4066 field_in(i,j,this%levshift+1:this%levshift+this%levused), &
4069 val_in(1:inused) = pack( &
4070 field_in(i,j,this%levshift+1:this%levshift+this%levused), &
4077 DO kk = 1, max(inused-kkcache-1, kkcache)
4079 kkdown = kkcache - kk + 1
4081 IF (kkdown >= 1)
THEN
4082 IF (this%vcoord_out(k) >= &
4083 min(coord_in(kkdown), coord_in(kkdown+1)) .AND. &
4084 this%vcoord_out(k) < &
4085 max(coord_in(kkdown), coord_in(kkdown+1)))
THEN
4092 IF (kkup < inused)
THEN
4093 IF (this%vcoord_out(k) >= &
4094 min(coord_in(kkup), coord_in(kkup+1)) .AND. &
4095 this%vcoord_out(k) < &
4096 max(coord_in(kkup), coord_in(kkup+1)))
THEN
4106 IF (
c_e(kfound))
THEN
4107 z1 = real((this%vcoord_out(k) - coord_in(kfound-1))/ &
4108 (coord_in(kfound) - coord_in(kfound-1)))
4110 IF (vartype == var_dir360)
THEN
4111 field_out(i,j,k) = &
4112 interp_var_360(val_in(kfound-1), val_in(kfound), z1, z2)
4113 ELSE IF (vartype == var_press)
THEN
4114 field_out(i,j,k) = exp(val_in(kfound-1)*z2 + val_in(kfound)*z1)
4116 field_out(i,j,k) = val_in(kfound-1)*z2 + val_in(kfound)*z1
4126 DEALLOCATE(coord_in,val_in)
4131ELSE IF (this%trans%trans_type ==
'' .OR. this%trans%trans_type ==
'none')
THEN
4133 field_out(:,:,:) = field_in(:,:,:)
4143FUNCTION interp_var_360(v1, v2, w1, w2)
4144REAL,
INTENT(in) :: v1, v2, w1, w2
4145REAL :: interp_var_360
4149IF (abs(v1 - v2) > 180.)
THEN
4157 interp_var_360 = modulo(lv1*w2 + lv2*w1, 360.)
4159 interp_var_360 = v1*w2 + v2*w1
4162END FUNCTION interp_var_360
4165RECURSIVE FUNCTION find_prevailing_direction(v1, l, h, res, mask)
RESULT(prev)
4166REAL,
INTENT(in) :: v1(:,:)
4167REAL,
INTENT(in) :: l, h, res
4168LOGICAL,
INTENT(in),
OPTIONAL :: mask(:,:)
4176IF ((h - l) <= res)
THEN
4181IF (
PRESENT(mask))
THEN
4182 nl = count(v1 >= l .AND. v1 < m .AND. mask)
4183 nh = count(v1 >= m .AND. v1 < h .AND. mask)
4185 nl = count(v1 >= l .AND. v1 < m)
4186 nh = count(v1 >= m .AND. v1 < h)
4189 prev = find_prevailing_direction(v1, m, h, res)
4190ELSE IF (nl > nh)
THEN
4191 prev = find_prevailing_direction(v1, l, m, res)
4192ELSE IF (nl == 0 .AND. nh == 0)
THEN
4198END FUNCTION find_prevailing_direction
4201END SUBROUTINE grid_transform_compute
4209SUBROUTINE grid_transform_v7d_grid_compute(this, field_in, field_out, var, &
4212REAL,
INTENT(in) :: field_in(:,:)
4213REAL,
INTENT(out):: field_out(:,:,:)
4214TYPE(vol7d_var),
INTENT(in),
OPTIONAL :: var
4215REAL,
INTENT(in),
OPTIONAL,
TARGET :: coord_3d_in(:,:,:)
4217real,
allocatable :: field_in_p(:),x_in_p(:),y_in_p(:)
4218INTEGER :: inn_p, ier, k
4219INTEGER :: innx, inny, innz, outnx, outny, outnz
4222call l4f_category_log(this%category,l4f_debug,
"start v7d_grid_transform_compute")
4225field_out(:,:,:) = rmiss
4227IF (.NOT.this%valid)
THEN
4229 "refusing to perform a non valid transformation")
4234innx =
SIZE(field_in,1); inny = 1; innz =
SIZE(field_in,2)
4235outnx =
SIZE(field_out,1); outny =
SIZE(field_out,2); outnz =
SIZE(field_out,3)
4238IF (this%trans%trans_type ==
'vertint')
THEN
4240 IF (innz /= this%innz)
THEN
4242 CALL l4f_category_log(this%category,l4f_error,
"inconsistent input shape: "//&
4243 t2c(this%innz)//
" /= "//t2c(innz))
4248 IF (outnz /= this%outnz)
THEN
4250 CALL l4f_category_log(this%category,l4f_error,
"inconsistent output shape: "//&
4251 t2c(this%outnz)//
" /= "//t2c(outnz))
4256 IF (innx /= outnx .OR. inny /= outny)
THEN
4258 CALL l4f_category_log(this%category,l4f_error,
"inconsistent hor. sizes: "//&
4259 t2c(innx)//
","//t2c(inny)//
" /= "//&
4260 t2c(outnx)//
","//t2c(outny))
4267 IF (innx /= this%innx .OR. inny /= this%inny)
THEN
4269 CALL l4f_category_log(this%category,l4f_error,
"inconsistent input shape: "//&
4270 t2c(this%innx)//
","//t2c(this%inny)//
" /= "//&
4271 t2c(innx)//
","//t2c(inny))
4276 IF (outnx /= this%outnx .OR. outny /= this%outny)
THEN
4278 CALL l4f_category_log(this%category,l4f_error,
"inconsistent output shape: "//&
4279 t2c(this%outnx)//
","//t2c(this%outny)//
" /= "//&
4280 t2c(outnx)//
","//t2c(outny))
4285 IF (innz /= outnz)
THEN
4287 CALL l4f_category_log(this%category,l4f_error,
"inconsistent vert. sizes: "//&
4288 t2c(innz)//
" /= "//t2c(outnz))
4297 "start grid_transform_v7d_grid_compute "//trim(this%trans%trans_type)//
':'// &
4298 trim(this%trans%sub_type))
4301IF (this%trans%trans_type ==
'inter')
THEN
4303 IF (this%trans%sub_type ==
'linear')
THEN
4305#ifdef HAVE_LIBNGMATH
4307 ALLOCATE(field_in_p(innx*inny), x_in_p(innx*inny), y_in_p(innx*inny))
4309 inn_p = count(
c_e(field_in(:,k)))
4312 "Number of sparse data points: "//t2c(inn_p)//
','//t2c(
SIZE(field_in(:,k))))
4316 field_in_p(1:inn_p) = pack(field_in(:,k),
c_e(field_in(:,k)))
4317 x_in_p(1:inn_p) = pack(this%inter_xp(:,1),
c_e(field_in(:,k)))
4318 y_in_p(1:inn_p) = pack(this%inter_yp(:,1),
c_e(field_in(:,k)))
4320 IF (.NOT.this%trans%extrap)
THEN
4321 CALL nnseti(
'ext', 0)
4322 CALL nnsetr(
'nul', rmiss)
4325 CALL natgrids(inn_p, x_in_p, y_in_p, field_in_p, &
4326 this%outnx, this%outny, real(this%inter_x(:,1)), &
4327 REAL(this%inter_y(1,:)), field_out(1,1,k), ier)
4331 "Error code from NCAR natgrids: "//t2c(ier))
4338 "insufficient data in gridded region to triangulate")
4342 DEALLOCATE(field_in_p, x_in_p, y_in_p)
4346 "libsim compiled without NATGRIDD (ngmath ncarg library)")
4353ELSE IF (this%trans%trans_type ==
'boxinter' .OR. &
4354 this%trans%trans_type ==
'polyinter' .OR. &
4355 this%trans%trans_type ==
'vertint' .OR. &
4356 this%trans%trans_type ==
'metamorphosis')
THEN
4359 reshape(field_in, (/
SIZE(field_in,1), 1,
SIZE(field_in,2)/)), field_out, var, &
4364END SUBROUTINE grid_transform_v7d_grid_compute
4379ELEMENTAL FUNCTION hbilin (z1,z2,z3,z4,x1,y1,x3,y3,xp,yp)
RESULT(zp)
4380REAL,
INTENT(in) :: z1,z2,z3,z4
4381DOUBLE PRECISION,
INTENT(in):: x1,y1