|
libsim Versione 8.0.0
|
◆ grid_transform_init()
Constructor for a grid_transform object, defining a particular grid-to-grid transformation. It defines an object describing a transformation from one rectangular grid to another; the abstract type of transformation is described in the transformation object trans (type transform_def) which must have been properly initialised. The additional information required here is the description of the input grid in (type griddim_def), the description of the output grid out (type griddim_def as well). The description of the output grid must be initialized for interpolating type transformations ('inter' and 'boxinter'), while it is generated by this constructor and returned in output for 'zoom', 'boxregrid', 'maskgen' and 'polyinter' transformations. The generated grid_transform object is specific to the input and output grids involved. The function c_e can be used in order to check whether the object has been successfully initialised, if the result is .FALSE., it should not be used further on.
Definizione alla linea 1418 del file grid_transform_class.F90. 1420 lout%dim%lon, lout%dim%lat, this%trans%extrap, &
1421 this%inter_index_x, this%inter_index_y)
1422
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))
1427
1428! compute coordinates of input grid
1429 CALL griddim_gen_coord(in, this%inter_x, this%inter_y)
1430! compute coordinates of output grid in input system
1431 CALL proj(in, lout%dim%lon, lout%dim%lat, this%inter_xp, this%inter_yp)
1432
1433 ELSE ! near, shapiro_near
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)
1438
1439 IF (this%trans%trans_type == 'intersearch') THEN ! replicate code above
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))
1444
1445! compute coordinates of input grid
1446 CALL griddim_gen_coord(in, this%inter_x, this%inter_y)
1447! compute coordinates of output grid in input system
1448 CALL proj(in, lout%dim%lon, lout%dim%lat, this%inter_xp, this%inter_yp)
1449 ENDIF
1450 ENDIF
1451
1452 CALL delete(lout)
1453 this%valid = .true.
1454 ENDIF
1455
1456ELSE IF (this%trans%trans_type == 'boxinter') THEN
1457
1458 CALL outgrid_setup() ! common setup for grid-generating methods
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)
1462! TODO now box size is ignored
1463! if box size not provided, use the actual grid step
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)
1468! half size is actually needed
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
1471! unlike before, here index arrays must have the shape of input grid
1472 ALLOCATE(this%inter_index_x(this%innx,this%inny), &
1473 this%inter_index_y(this%innx,this%inny))
1474
1475! compute coordinates of input grid in geo system
1476 CALL copy(in, lin)
1477 CALL unproj(lin)
1478! use find_index in the opposite way, here extrap does not make sense
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)
1483
1484 CALL delete(lin)
1485 this%valid = .true. ! warning, no check of subtype
1486
1487ELSE IF (this%trans%trans_type == 'stencilinter') THEN
1488
1489 CALL outgrid_setup() ! common setup for grid-generating methods
1490! from inter:near
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)
1494
1495 ALLOCATE (this%inter_index_x(this%outnx,this%outny), &
1496 this%inter_index_y(this%outnx,this%outny))
1497 CALL copy(out, lout)
1498 CALL unproj(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)
1503
1504! define the stencil mask
1505 nr = int(this%trans%area_info%radius) ! integer radius
1506 n = nr*2+1 ! n. of points
1507 nm = nr + 1 ! becomes index of center
1508 r2 = this%trans%area_info%radius**2
1509 ALLOCATE(this%stencil(n,n))
1510 this%stencil(:,:) = .true.
1511 DO iy = 1, n
1512 DO ix = 1, n
1513 IF ((ix-nm)**2+(iy-nm)**2 > r2) this%stencil(ix,iy) = .false.
1514 ENDDO
1515 ENDDO
1516
1517! set to missing the elements of inter_index too close to the domain
1518! borders
1519 xnmin = nr + 1
1520 xnmax = this%innx - nr
1521 ynmin = nr + 1
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
1531 ENDIF
1532 ENDDO
1533 ENDDO
1534
1535#ifdef DEBUG
1536 CALL l4f_category_log(this%category, l4f_debug, &
1537 'stencilinter: stencil size '//t2c(n*n))
1538 CALL l4f_category_log(this%category, l4f_debug, &
1539 'stencilinter: stencil points '//t2c(count(this%stencil)))
1540#endif
1541
1542 CALL delete(lout)
1543 this%valid = .true. ! warning, no check of subtype
1544
1545ELSE IF (this%trans%trans_type == 'maskgen') THEN
1546
1547 IF (this%trans%sub_type == 'poly') THEN
1548
1549 CALL copy(in, out)
1550 CALL get_val(in, nx=this%innx, ny=this%inny)
1551 this%outnx = this%innx
1552 this%outny = this%inny
1553
1554! unlike before, here index arrays must have the shape of input grid
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
1559
1560! compute coordinates of input grid in geo system
1561 CALL unproj(out) ! should be unproj(lin)
1562
1563 nprev = 1
1564!$OMP PARALLEL DEFAULT(SHARED)
1565!$OMP DO PRIVATE(j, i, n, point) FIRSTPRIVATE(nprev)
1566 DO j = 1, this%inny
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))
1569
1570 DO n = nprev, this%trans%poly%arraysize ! optimize starting from last matched polygon
1571 IF (inside(point, this%trans%poly%array(n))) THEN ! stop at the first matching polygon
1572 this%inter_index_x(i,j) = n
1573 nprev = n
1574 cycle inside_x
1575 ENDIF
1576 ENDDO
1577 DO n = nprev-1, 1, -1 ! test the other polygons
1578 IF (inside(point, this%trans%poly%array(n))) THEN ! stop at the first matching polygon
1579 this%inter_index_x(i,j) = n
1580 nprev = n
1581 cycle inside_x
1582 ENDIF
1583 ENDDO
1584
1585! CALL delete(point) ! speedup
1586 ENDDO inside_x
1587 ENDDO
1588!$OMP END PARALLEL
1589
1590 ELSE IF (this%trans%sub_type == 'grid') THEN
1591! here out(put grid) is abused for indicating the box-generating grid
1592! but the real output grid is the input grid
1593 CALL copy(out, lout) ! save out for local use
1594 CALL delete(out) ! needed before copy
1595 CALL copy(in, out)
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)
1601
1602! unlike before, here index arrays must have the shape of input grid
1603 ALLOCATE(this%inter_index_x(this%innx,this%inny), &
1604 this%inter_index_y(this%innx,this%inny))
1605
1606! compute coordinates of input/output grid in geo system
1607 CALL unproj(out)
1608
1609! use find_index in the opposite way, here extrap does not make sense
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)
1614! transform indices to 1-d for mask generation
1615 WHERE(c_e(this%inter_index_x(:,:)))
1616 this%inter_index_x(:,:) = this%inter_index_x(:,:) + &
1617 (this%inter_index_y(:,:)-1)*nx
1618 END WHERE
1619
1620 CALL delete(lout)
1621 ENDIF
1622
1623 this%valid = .true.
1624
1625ELSE IF (this%trans%trans_type == 'polyinter') THEN
1626
1627! this is the only difference wrt maskgen:poly
1628 this%recur = .true. ! grid-to-grid polyinter is done in two steps!
1629
1630 CALL copy(in, out)
1631 CALL get_val(in, nx=this%innx, ny=this%inny)
1632 this%outnx = this%innx
1633 this%outny = this%inny
1634
1635! unlike before, here index arrays must have the shape of input grid
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
1640
1641! compute coordinates of input grid in geo system
1642 CALL unproj(out) ! should be unproj(lin)
1643
1644 nprev = 1
1645!$OMP PARALLEL DEFAULT(SHARED)
1646!$OMP DO PRIVATE(j, i, n, point) FIRSTPRIVATE(nprev)
1647 DO j = 1, this%inny
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))
1650
1651 DO n = nprev, this%trans%poly%arraysize ! optimize starting from last matched polygon
1652 IF (inside(point, this%trans%poly%array(n))) THEN ! stop at the first matching polygon
1653 this%inter_index_x(i,j) = n
1654 nprev = n
1655 cycle inside_x_2
1656 ENDIF
1657 ENDDO
1658 DO n = nprev-1, 1, -1 ! test the other polygons
1659 IF (inside(point, this%trans%poly%array(n))) THEN ! stop at the first matching polygon
1660 this%inter_index_x(i,j) = n
1661 nprev = n
1662 cycle inside_x_2
1663 ENDIF
1664 ENDDO
1665
1666! CALL delete(point) ! speedup
1667 ENDDO inside_x_2
1668 ENDDO
1669!$OMP END PARALLEL
1670
1671 this%valid = .true. ! warning, no check of subtype
1672
1673ELSE IF (this%trans%trans_type == 'metamorphosis') THEN
1674
1675 CALL copy(in, out)
1676 CALL get_val(in, nx=this%innx, ny=this%inny)
1677 this%outnx = this%innx
1678 this%outny = this%inny
1679
1680 IF (this%trans%sub_type == 'maskvalid' .OR. this%trans%sub_type == 'maskinvalid') THEN
1681
1682 IF (.NOT.PRESENT(maskgrid)) THEN
1683 CALL l4f_category_log(this%category,l4f_error, &
1684 'grid_transform_init maskgrid argument missing for metamorphosis:'// &
1685 trim(this%trans%sub_type)//' transformation')
1686 CALL raise_error()
1687 RETURN
1688 ENDIF
1689
1690 IF (this%innx /= SIZE(maskgrid,1) .OR. this%inny /= SIZE(maskgrid,2)) THEN
1691 CALL l4f_category_log(this%category,l4f_error, &
1692 'grid_transform_init mask non conformal with input field')
1693 CALL l4f_category_log(this%category,l4f_error, &
1694 'mask: '//t2c(SIZE(maskgrid,1))//'x'//t2c(SIZE(maskgrid,2))// &
1695 ' input field:'//t2c(this%innx)//'x'//t2c(this%inny))
1696 CALL raise_error()
1697 RETURN
1698 ENDIF
1699
1700 ALLOCATE(this%point_mask(this%innx,this%inny))
1701
1702 IF (this%trans%sub_type == 'maskvalid') THEN
1703! behavior depends on the presence/usability of maskbounds,
1704! simplified wrt its use in metamorphosis:mask
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(:,:))
1709 ELSE
1710 this%point_mask(:,:) = c_e(maskgrid(:,:)) .AND. &
1711 maskgrid(:,:) > maskbounds(1) .AND. &
1712 maskgrid(:,:) <= maskbounds(SIZE(maskbounds))
1713 ENDIF
1714 ELSE ! reverse condition
1715 this%point_mask(:,:) = .NOT.c_e(maskgrid(:,:))
1716 ENDIF
1717
1718 this%valid = .true.
1719
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
1724! here i can only store field for computing mask runtime
1725
1726 this%val_mask = maskgrid
1727 this%valid = .true.
1728
1729 ELSE IF (this%trans%sub_type == 'setinvalidto') THEN
1730
1731 IF (.NOT.PRESENT(maskbounds)) THEN
1732 CALL l4f_category_log(this%category,l4f_error, &
1733 'grid_transform_init maskbounds missing for metamorphosis:'// &
1734 trim(this%trans%sub_type)//' transformation')
1735 RETURN
1736 ELSE IF (SIZE(maskbounds) < 1) THEN
1737 CALL l4f_category_log(this%category,l4f_error, &
1738 'grid_transform_init maskbounds empty for metamorphosis:'// &
1739 trim(this%trans%sub_type)//' transformation')
1740 RETURN
1741 ELSE
1742 this%val1 = maskbounds(1)
1743#ifdef DEBUG
1744 CALL l4f_category_log(this%category, l4f_debug, &
1745 "grid_transform_init setting invalid data to "//t2c(this%val1))
1746#endif
1747 ENDIF
1748
1749 this%valid = .true.
1750
1751 ELSE IF (this%trans%sub_type == 'settoinvalid') THEN
1752
1753 IF (.NOT.PRESENT(maskbounds)) THEN
1754 CALL l4f_category_log(this%category,l4f_error, &
1755 'grid_transform_init maskbounds missing for metamorphosis:'// &
1756 trim(this%trans%sub_type)//' transformation')
1757 CALL raise_error()
1758 RETURN
1759 ELSE IF (SIZE(maskbounds) < 2) THEN
1760 CALL l4f_category_log(this%category,l4f_error, &
1761 'grid_transform_init maskbounds must have at least 2 elements for metamorphosis:'// &
1762 trim(this%trans%sub_type)//' transformation')
1763 CALL raise_error()
1764 RETURN
1765 ELSE
1766 this%val1 = maskbounds(1)
1767 this%val2 = maskbounds(SIZE(maskbounds))
1768#ifdef DEBUG
1769 CALL l4f_category_log(this%category, l4f_debug, &
1770 "grid_transform_init setting to invalid interval ]"//t2c(this%val1)//','// &
1771 t2c(this%val2)//']')
1772#endif
1773 ENDIF
1774
1775 this%valid = .true.
1776
1777 ENDIF
1778
1779ENDIF
1780
1781CONTAINS
1782
1783! local subroutine to be called by all methods interpolating to a new
1784! grid, no parameters passed, used as a macro to avoid repeating code
1785SUBROUTINE outgrid_setup()
1786
1787! set increments in new grid in order for all the baraque to work
1788CALL griddim_setsteps(out)
1789! check component flag
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
1793! same projection: set output component flag equal to input regardless
1794! of its value
1795 CALL set_val(out, component_flag=cf_i)
1796ELSE
1797! different projection, interpolation possible only with vector data
1798! referred to geograpical axes
1799 IF (cf_i == 1) THEN
1800 CALL l4f_category_log(this%category,l4f_warn, &
1801 'trying to interpolate a grid with component flag 1 to a grid on a different projection')
1802 CALL l4f_category_log(this%category,L4F_WARN, &
1803 'vector fields will probably be wrong')
1804 ELSE
1805 CALL set_val(out, component_flag=cf_i)
1806 ENDIF
1807ENDIF
1808! rotate the input grid by n*360 degrees to bring it closer to the output grid
1809CALL griddim_set_central_lon(in, griddim_central_lon(out))
1810
1811END SUBROUTINE outgrid_setup
1812
1813END SUBROUTINE grid_transform_init
1814
1815
1816!> Constructor for a \a grid_transform object, defining a particular
1817!! grid-to-sparse points transformation.
1818!! It defines an object describing a transformation from a rectangular
1819!! grid to a set of sparse points; the abstract type of transformation
1820!! is described in the transformation object \a trans (type
1821!! transform_def) which must have been properly initialised. The
1822!! additional information required here is the description of the
1823!! input grid \a in (type griddim_def), and, if required by the
1824!! transformation type, the information about the target sparse points
1825!! over which the transformation should take place:
1826!!
1827!! - for 'inter' transformation, this is provided in the form of a
1828!! vol7d object (\a v7d_out argument, input), which must have been
1829!! initialized with the coordinates of desired sparse points
1830!!
1831!! - for 'polyinter' transformation, no target point information has
1832!! to be provided in input (it is calculated on the basis of input
1833!! grid and \a trans object), and the coordinates of the target
1834!! points (polygons' centroids) are returned in output in \a
1835!! v7d_out argument
1836!!
1837!! - for 'maskinter' transformation, this is a two dimensional real
1838!! field (\a maskgrid argument), which, together with the \a
1839!! maskbounds argument (optional with default), divides the input
1840!! grid in a number of subareas according to the values of \a
1841!! maskinter, and, in this case, \a v7d_out is an output argument
1842!! which returns the coordinates of the target points (subareas'
1843!! centroids)
1844!!
1845!! - for 'metamorphosis' transformation, no target point information
1846!! has to be provided in input (it is calculated on the basis of
1847!! input grid and \a trans object), except for 'mask' subtype, for
1848!! which the same information as for 'maskinter' transformation has
1849!! to be provided; in all the cases, as for 'polyinter', the
1850!! information about target points is returned in output in \a
1851!! v7d_out argument.
1852!!
1853!! The generated \a grid_transform object is specific to the grid and
1854!! sparse point list provided or computed. The function \a c_e can be
1855!! used in order to check whether the object has been successfully
1856!! initialised, if the result is \a .FALSE., it should not be used
1857!! further on.
1858SUBROUTINE grid_transform_grid_vol7d_init(this, trans, in, v7d_out, &
1859 maskgrid, maskbounds, find_index, categoryappend)
1860TYPE(grid_transform),INTENT(out) :: this !< grid_transformation object
1861TYPE(transform_def),INTENT(in) :: trans !< transformation object
1862TYPE(griddim_def),INTENT(in) :: in !< griddim object to transform
1863TYPE(vol7d),INTENT(inout) :: v7d_out !< vol7d object with the coordinates of the sparse points to be used as transformation target (input or output depending on type of transformation)
1864REAL,INTENT(in),OPTIONAL :: maskgrid(:,:) !< 2D field to be used for defining subareas according to its values, it must have the same shape as the field to be interpolated (for transformation type 'maskinter' and 'metamorphosis:mask')
1865REAL,INTENT(in),OPTIONAL :: maskbounds(:) !< array of boundary values for defining subareas from the values of \a maskgrid, the number of subareas is SIZE(maskbounds) - 1, if not provided a default based on extreme values of \a maskgrid is used
1866PROCEDURE(basic_find_index),POINTER,OPTIONAL :: find_index
1867CHARACTER(len=*),INTENT(in),OPTIONAL :: categoryappend !< append this suffix to log4fortran namespace category
1868
1869INTEGER :: ix, iy, n, nm, nr, nprev, nmaskarea, xnmin, xnmax, ynmin, ynmax, &
1870 time_definition
1871DOUBLE PRECISION :: xmin, xmax, ymin, ymax, r2, lonref
1872DOUBLE PRECISION,ALLOCATABLE :: lon1(:), lat1(:), lon(:,:), lat(:,:)
1873REAL,ALLOCATABLE :: lmaskbounds(:)
1874TYPE(georef_coord) :: point
1875TYPE(griddim_def) :: lin
1876!$ INTEGER :: outnx
1877
1878IF (PRESENT(find_index)) THEN ! move in init_common?
1879 IF (ASSOCIATED(find_index)) THEN
1880 this%find_index => find_index
1881 ENDIF
1882ENDIF
1883CALL grid_transform_init_common(this, trans, categoryappend)
1884#ifdef DEBUG
1885CALL l4f_category_log(this%category, L4F_DEBUG, "grid_transform vg6d-v7d")
1886#endif
1887
1888! used after in some transformations
1889CALL get_val(trans, time_definition=time_definition)
1890IF (.NOT. c_e(time_definition)) THEN
1891 time_definition=1 ! default to validity time
1892ENDIF
1893
1894IF (this%trans%trans_type == 'inter') THEN
1895
1896 IF (this%trans%sub_type == 'near' .OR. this%trans%sub_type == 'bilin' &
1897 .OR. this%trans%sub_type == 'shapiro_near') THEN
1898
1899 CALL copy(in, lin)
1900 CALL get_val(lin, nx=this%innx, ny=this%inny)
1901 this%outnx = SIZE(v7d_out%ana)
1902 this%outny = 1
1903
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))
1907
1908 CALL getval(v7d_out%ana(:)%coord,lon=lon(:,1),lat=lat(:,1))
1909! equalize in/out coordinates
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)
1913
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)
1919
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))
1922
1923 CALL griddim_gen_coord(lin, this%inter_x, this%inter_y)
1924 CALL proj(lin, lon, lat, this%inter_xp, this%inter_yp)
1925
1926 ELSE ! near shapiro_near
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)
1931
1932 IF (this%trans%trans_type == 'intersearch') THEN ! replicate code above
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))
1935
1936 CALL griddim_gen_coord(lin, this%inter_x, this%inter_y)
1937 CALL proj(lin, lon, lat, this%inter_xp, this%inter_yp)
1938 ENDIF
1939 ENDIF
1940
1941 DEALLOCATE(lon,lat)
1942 CALL delete(lin)
1943
1944 this%valid = .true.
1945
1946 ENDIF
1947
1948ELSE IF (this%trans%trans_type == 'polyinter') THEN
1949
1950 CALL get_val(in, nx=this%innx, ny=this%inny)
1951! unlike before, here index arrays must have the shape of input grid
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
1956
1957! compute coordinates of input grid in geo system
1958 CALL copy(in, lin)
1959 CALL unproj(lin)
1960
1961 this%outnx = this%trans%poly%arraysize
1962 this%outny = 1
1963 CALL delete(v7d_out) ! required to avoid leaks because intent(inout), dangerous
1964 CALL init(v7d_out, time_definition=time_definition)
1965 CALL vol7d_alloc(v7d_out, nana=this%outnx)
1966
1967! equalize in/out coordinates
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)
1972 DEALLOCATE(lon)
1973
1974! setup output point list, equal to average of polygon points
1975! warning, in case of concave areas points may coincide!
1976 CALL poly_to_coordinates(this%trans%poly, v7d_out)
1977
1978 nprev = 1
1979!$OMP PARALLEL DEFAULT(SHARED)
1980!$OMP DO PRIVATE(iy, ix, n, point) FIRSTPRIVATE(nprev)
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))
1984
1985 DO n = nprev, this%trans%poly%arraysize ! optimize starting from last matched polygon
1986 IF (inside(point, this%trans%poly%array(n))) THEN ! stop at the first matching polygon
1987 this%inter_index_x(ix,iy) = n
1988 nprev = n
1989 cycle inside_x
1990 ENDIF
1991 ENDDO
1992 DO n = nprev-1, 1, -1 ! test the other polygons
1993 IF (inside(point, this%trans%poly%array(n))) THEN ! stop at the first matching polygon
1994 this%inter_index_x(ix,iy) = n
1995 nprev = n
1996 cycle inside_x
1997 ENDIF
1998 ENDDO
1999
2000! CALL delete(point) ! speedup
|