libsim Versione 8.0.0

◆ volgrid6d_var_hor_comp_index()

subroutine, public volgrid6d_var_hor_comp_index ( type(volgrid6d_var), dimension(:), intent(in) this,
integer, dimension(:), pointer xind,
integer, dimension(:), pointer yind )

Locate variables which are horizontal components of a vector field.

This method scans the volgrid6d_var array provided and locates pairs of variables which are x and y component of the same vector field. On exit, the arrays \x xind(:) and yind(:) are allocated to a size equal to the number of vector fields detected and their corresponding elements will point to x and y components of the same vector field. If inconsistencies are found, e.g. only one component is detected for a field, or more than one input variable define the same component, then xind and xind are nullified, thus an error condition can be tested as .NOT.ASSOCIATED(xind). If no vector fields are found then xind and xind are allocated to zero size. If xind and yind are ASSOCIATED() after return, they should be DEALLOCATEd by the calling procedure.

Parametri
[in]thisarray of volgrid6d_var objects (grib variable) to test
yindoutput arrays of indices pointing to matching horizontal components, allocated by this method

Definizione alla linea 1480 del file volgrid6d_var_class.F90.

1481! Copyright (C) 2010 ARPA-SIM <urpsim@smr.arpa.emr.it>
1482! authors:
1483! Davide Cesari <dcesari@arpa.emr.it>
1484! Paolo Patruno <ppatruno@arpa.emr.it>
1485
1486! This program is free software; you can redistribute it and/or
1487! modify it under the terms of the GNU General Public License as
1488! published by the Free Software Foundation; either version 2 of
1489! the License, or (at your option) any later version.
1490
1491! This program is distributed in the hope that it will be useful,
1492! but WITHOUT ANY WARRANTY; without even the implied warranty of
1493! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1494! GNU General Public License for more details.
1495
1496! You should have received a copy of the GNU General Public License
1497! along with this program. If not, see <http://www.gnu.org/licenses/>.
1498#include "config.h"
1499
1500!> Class for managing physical variables in a grib 1/2 fashion.
1501!! This module defines a class which can represent Earth-science
1502!! related physical variables, following the classification scheme
1503!! adopted by WMO for grib1 and grib2 parameter definition. It also
1504!! defines some methods for mapping \a volgrid6d_var variables and
1505!! converting the corresponding fields to a matching \a vol7d_var
1506!! object defined in \a vol7d_var_class module, which, unlike the
1507!! variables defined here, defines univocally a physical quantity.
1508!!
1509!! \ingroup volgrid6d
1511USE kinds
1513USE err_handling
1516USE grid_id_class
1517
1518IMPLICIT NONE
1519
1520!> Definition of a physical variable in grib coding style.
1521!! \a volgrid6d_var members are public, thus they can be freely
1522!! altered, but it is advisable to set them through the
1523!! volgrid6d_var_class::init constructor.
1524TYPE volgrid6d_var
1525 integer :: centre !< centre
1526 integer :: category !< grib2: category / grib1: grib table version number
1527 integer :: number !< parameter number
1528 integer :: discipline !< grib2: discipline / grib1: 255
1529 CHARACTER(len=65) :: description !< optional textual description of the variable
1530 CHARACTER(len=24) :: unit !< optional textual description of the variable's unit
1531END TYPE volgrid6d_var
1532
1533TYPE(volgrid6d_var),PARAMETER :: volgrid6d_var_miss= &
1534 volgrid6d_var(imiss,imiss,imiss,imiss,cmiss,cmiss) !< missing value volgrid6d_var.
1535
1536TYPE(vol7d_var),PARAMETER :: vol7d_var_horstag(2) = (/ &
1537 vol7d_var('B11003', '', '', 0, 0, 0, 0, 0, 0), &
1538 vol7d_var('B11004', '', '', 0, 0, 0, 0, 0, 0) &
1539 /)
1540
1541TYPE(vol7d_var),PARAMETER :: vol7d_var_horcomp(4) = (/ &! RESHAPE( (/ &
1542 vol7d_var('B11003', '', '', 0, 0, 0, 0, 0, 0), &
1543 vol7d_var('B11004', '', '', 0, 0, 0, 0, 0, 0), &
1544 vol7d_var('B11200', '', '', 0, 0, 0, 0, 0, 0), &
1545 vol7d_var('B11201', '', '', 0, 0, 0, 0, 0, 0) &
1546/)
1547!/), (/2,2/)) ! bug in gfortran
1548
1549!> Class defining a real conversion function between units. It is
1550!! used to numerically convert a value expressed as a \a volgrid6d_var
1551!! variable in a value expressed as a \a vol7d_var variable and
1552!! vice-versa. At the moment only a linear conversion is
1553!! supported. Objects of this class are returned only by the \a
1554!! vargrib2varbufr \a varbufr2vargrib, and \a convert methods and are
1555!! used in the \a convert and \a compute methods defined in this
1556!! MODULE.
1557TYPE conv_func
1558 PRIVATE
1559 REAL :: a, b
1560END TYPE conv_func
1561
1562TYPE(conv_func), PARAMETER :: conv_func_miss=conv_func(rmiss,rmiss)
1563TYPE(conv_func), PARAMETER :: conv_func_identity=conv_func(1.0,0.0)
1564
1565TYPE vg6d_v7d_var_conv
1566 TYPE(volgrid6d_var) :: vg6d_var
1567 TYPE(vol7d_var) :: v7d_var
1568 TYPE(conv_func) :: c_func
1569! aggiungere informazioni ad es. su rotazione del vento
1570END TYPE vg6d_v7d_var_conv
1571
1572TYPE(vg6d_v7d_var_conv), PARAMETER :: vg6d_v7d_var_conv_miss= &
1573 vg6d_v7d_var_conv(volgrid6d_var_miss, vol7d_var_miss, conv_func_miss)
1574
1575TYPE(vg6d_v7d_var_conv), ALLOCATABLE :: conv_fwd(:), conv_bwd(:)
1576
1577!> Initialize a \a volgrid6d_var object with the optional arguments provided.
1578!! If an argument is not provided, the corresponding object member and
1579!! those depending on it will be set to missing. For grib1-style
1580!! variables, the \a discipline argument must be omitted, it will be
1581!! set to 255 (grib missing value).
1582!!
1583!! \param this TYPE(volgrid6d_var),INTENT(INOUT) object to be initialized
1584!! \param centre INTEGER,INTENT(in),OPTIONAL centre
1585!! \param category INTEGER,INTENT(in),OPTIONAL grib2: category / grib1: grib table version number
1586!! \param number INTEGER,INTENT(in),OPTIONAL parameter number
1587!! \param discipline INTEGER,INTENT(in),OPTIONAL grib2: discipline / grib1: 255
1588!! \param description CHARACTER(len=*),INTENT(in),OPTIONAL optional textual description of the variable
1589!! \param unit CHARACTER(len=*),INTENT(in),OPTIONAL optional textual description of the variable's unit
1590INTERFACE init
1591 MODULE PROCEDURE volgrid6d_var_init
1592END INTERFACE
1593
1594!> Destructor for the corresponding object, it assigns it to a missing value.
1595!! \param this TYPE(volgrid6d_var) object to be destroyed
1596INTERFACE delete
1597 MODULE PROCEDURE volgrid6d_var_delete
1598END INTERFACE
1599
1600INTERFACE c_e
1601 MODULE PROCEDURE volgrid6d_var_c_e
1602END INTERFACE
1603
1604
1605!> Logical equality operators for objects of the classes \a
1606!! volgrid6d_var and \a conv_func.
1607!! They are all defined as \c ELEMENTAL thus work also on arrays of
1608!! any shape.
1609INTERFACE OPERATOR (==)
1610 MODULE PROCEDURE volgrid6d_var_eq, conv_func_eq
1611END INTERFACE
1612
1613!> Logical inequality operators for objects of the classes \a
1614!! volgrid6d_var and \a conv_func.
1615!! They are all defined as \c ELEMENTAL thus work also on arrays of
1616!! any shape.
1617INTERFACE OPERATOR (/=)
1618 MODULE PROCEDURE volgrid6d_var_ne, conv_func_ne
1619END INTERFACE
1620
1621#define VOL7D_POLY_TYPE TYPE(volgrid6d_var)
1622#define VOL7D_POLY_TYPES _var6d
1623#include "array_utilities_pre.F90"
1624
1625!> Display on the screen a brief content of object
1626INTERFACE display
1627 MODULE PROCEDURE display_volgrid6d_var
1628END INTERFACE
1629
1630!> Compose two conversions into a single one.
1631!! Unlike scalar multiplication (and like matrix multiplication) here
1632!! a*b /= b*a. By convention, the second factor is applied first in
1633!! the result.
1634INTERFACE OPERATOR (*)
1635 MODULE PROCEDURE conv_func_mult
1636END INTERFACE OPERATOR (*)
1637
1638!> Apply the conversion function \a this to \a values.
1639!! function version
1640INTERFACE compute
1641 MODULE PROCEDURE conv_func_compute
1642END INTERFACE
1643
1644!> Apply the conversion function \a this to \a values.
1645!! subroutine version
1646INTERFACE convert
1647 MODULE PROCEDURE varbufr2vargrib_convert, vargrib2varbufr_convert
1648END INTERFACE
1649
1650PRIVATE
1651PUBLIC volgrid6d_var, volgrid6d_var_miss, volgrid6d_var_new, init, delete, &
1652 c_e, volgrid6d_var_normalize, &
1653 OPERATOR(==), OPERATOR(/=), OPERATOR(*), &
1654 count_distinct, pack_distinct, count_and_pack_distinct, &
1655 map_distinct, map_inv_distinct, &
1656 index, display, &
1657 vargrib2varbufr, varbufr2vargrib, &
1658 conv_func, conv_func_miss, compute, convert, &
1659 volgrid6d_var_hor_comp_index, volgrid6d_var_is_hor_comp
1660
1661
1662CONTAINS
1663
1664
1665ELEMENTAL FUNCTION volgrid6d_var_new(centre, category, number, &
1666 discipline, description, unit) RESULT(this)
1667integer,INTENT(in),OPTIONAL :: centre !< centre
1668integer,INTENT(in),OPTIONAL :: category !< grib2: category / grib1: grib table version number
1669integer,INTENT(in),OPTIONAL :: number !< parameter number
1670integer,INTENT(in),OPTIONAL :: discipline !< grib2: discipline
1671CHARACTER(len=*),INTENT(in),OPTIONAL :: description !< textual description of the variable
1672CHARACTER(len=*),INTENT(in),OPTIONAL :: unit !< textual description of the variable's unit
1673
1674TYPE(volgrid6d_var) :: this !< object to be initialised
1675
1676CALL init(this, centre, category, number, discipline, description, unit)
1677
1678END FUNCTION volgrid6d_var_new
1679
1680
1681! documented in the interface
1682ELEMENTAL SUBROUTINE volgrid6d_var_init(this, centre, category, number, discipline,description,unit)
1683TYPE(volgrid6d_var),INTENT(INOUT) :: this ! object to be initialized
1684INTEGER,INTENT(in),OPTIONAL :: centre ! centre
1685INTEGER,INTENT(in),OPTIONAL :: category ! grib2: category / grib1: grib table version number
1686INTEGER,INTENT(in),OPTIONAL :: number ! parameter number
1687INTEGER,INTENT(in),OPTIONAL :: discipline ! grib2: discipline / grib1: 255
1688CHARACTER(len=*),INTENT(in),OPTIONAL :: description ! optional textual description of the variable
1689CHARACTER(len=*),INTENT(in),OPTIONAL :: unit ! optional textual description of the variable's unit
1690
1691IF (PRESENT(centre)) THEN
1692 this%centre = centre
1693ELSE
1694 this%centre = imiss
1695 this%category = imiss
1696 this%number = imiss
1697 this%discipline = imiss
1698 RETURN
1699ENDIF
1700
1701IF (PRESENT(category)) THEN
1702 this%category = category
1703ELSE
1704 this%category = imiss
1705 this%number = imiss
1706 this%discipline = imiss
1707 RETURN
1708ENDIF
1709
1710
1711IF (PRESENT(number)) THEN
1712 this%number = number
1713ELSE
1714 this%number = imiss
1715 this%discipline = imiss
1716 RETURN
1717ENDIF
1718
1719! se sono arrivato fino a qui ho impostato centre, category e number
1720!per il grib 1 manca discipline e imposto 255 (missing del grib2)
1721
1722IF (PRESENT(discipline)) THEN
1723 this%discipline = discipline
1724ELSE
1725 this%discipline = 255
1726ENDIF
1727
1728IF (PRESENT(description)) THEN
1729 this%description = description
1730ELSE
1731 this%description = cmiss
1732ENDIF
1733
1734IF (PRESENT(unit)) THEN
1735 this%unit = unit
1736ELSE
1737 this%unit = cmiss
1738ENDIF
1739
1740
1741
1742END SUBROUTINE volgrid6d_var_init
1743
1744
1745! documented in the interface
1746SUBROUTINE volgrid6d_var_delete(this)
1747TYPE(volgrid6d_var),INTENT(INOUT) :: this
1748
1749this%centre = imiss
1750this%category = imiss
1751this%number = imiss
1752this%discipline = imiss
1753this%description = cmiss
1754this%unit = cmiss
1755
1756END SUBROUTINE volgrid6d_var_delete
1757
1758
1759ELEMENTAL FUNCTION volgrid6d_var_c_e(this) RESULT(c_e)
1760TYPE(volgrid6d_var),INTENT(IN) :: this
1761LOGICAL :: c_e
1762c_e = this /= volgrid6d_var_miss
1763END FUNCTION volgrid6d_var_c_e
1764
1765
1766ELEMENTAL FUNCTION volgrid6d_var_eq(this, that) RESULT(res)
1767TYPE(volgrid6d_var),INTENT(IN) :: this, that
1768LOGICAL :: res
1769
1770IF (this%discipline == that%discipline) THEN
1771
1772 IF (this%discipline == 255) THEN ! grib1, WMO tables are all equivalent
1773 res = ((this%category == that%category) .OR. &
1774 (this%category >= 1 .AND. this%category <=3 .AND. &
1775 that%category >= 1 .AND. that%category <=3)) .AND. &
1776 this%number == that%number
1777
1778 IF ((this%category >= 128 .AND. this%category <= 254) .OR. &
1779 (this%number >= 128 .AND. this%number <= 254)) THEN
1780 res = res .AND. this%centre == that%centre ! local definition, centre matters
1781 ENDIF
1782
1783 ELSE ! grib2
1784 res = this%category == that%category .AND. &
1785 this%number == that%number
1786
1787 IF ((this%discipline >= 192 .AND. this%discipline <= 254) .OR. &
1788 (this%category >= 192 .AND. this%category <= 254) .OR. &
1789 (this%number >= 192 .AND. this%number <= 254)) THEN
1790 res = res .AND. this%centre == that%centre ! local definition, centre matters
1791 ENDIF
1792 ENDIF
1793
1794ELSE ! different edition or different discipline
1795 res = .false.
1796ENDIF
1797
1798END FUNCTION volgrid6d_var_eq
1799
1800
1801ELEMENTAL FUNCTION volgrid6d_var_ne(this, that) RESULT(res)
1802TYPE(volgrid6d_var),INTENT(IN) :: this, that
1803LOGICAL :: res
1804
1805res = .NOT.(this == that)
1806
1807END FUNCTION volgrid6d_var_ne
1808
1809
1810#include "array_utilities_inc.F90"
1811
1812
1813!> Display on the screen a brief content of \a volgrid6d_var object.
1814SUBROUTINE display_volgrid6d_var(this)
1815TYPE(volgrid6d_var),INTENT(in) :: this !< volgrid6d_var object to display
1816
1817print*,"GRIDVAR: ",this%centre,this%discipline,this%category,this%number
1818
1819END SUBROUTINE display_volgrid6d_var
1820
1821
1822!> Convert a \a volgrid6d_var array object into a physically equivalent
1823!! \a vol7d_var array object. This method converts a grib-like array
1824!! of physical variables \a vargrib, to an array of unique, physically
1825!! based, bufr-like variables \a varbufr. The output array must have
1826!! enough room for the converted variables. The method additionally
1827!! allocates a \a conv_func array object of the same size, which can
1828!! successively be used to convert the numerical values of the fields
1829!! associated to \a vargrib to the corresponding fields in the \a
1830!! bufr-like representation. \a c_func will have to be deallocated by
1831!! the calling procedure. If a conversion is not successful, the
1832!! corresponding output variable is set to \a vol7d_var_miss and the
1833!! conversion function to \a conv_func_miss.
1834SUBROUTINE vargrib2varbufr(vargrib, varbufr, c_func)
1835TYPE(volgrid6d_var),INTENT(in) :: vargrib(:) !< array of input grib-like variables
1836TYPE(vol7d_var),INTENT(out) :: varbufr(:) !< array of output bufr-like variables
1837TYPE(conv_func),POINTER :: c_func(:) !< pointer to an array of the corresponding \a conv_func objects, allocated in the method
1838
1839INTEGER :: i, n, stallo
1840
1841n = min(SIZE(varbufr), SIZE(vargrib))
1842ALLOCATE(c_func(n),stat=stallo)
1843IF (stallo /= 0) THEN
1844 call l4f_log(l4f_fatal,"allocating memory")
1845 call raise_fatal_error()
1846ENDIF
1847
1848DO i = 1, n
1849 varbufr(i) = convert(vargrib(i), c_func(i))
1850ENDDO
1851
1852END SUBROUTINE vargrib2varbufr
1853
1854
1855!> Convert a \a volgrid6d_var object into a physically equivalent
1856!! \a vol7d_var object. This method returns a physically based,
1857!! bufr-like representation of type \a vol7d_var of the grib-like
1858!! input physical variable \a vargrib. The method optionally returns
1859!! a \a conv_func object which can successively be used to convert the
1860!! numerical values of the field associated to \a vargrib to the
1861!! corresponding fields in the bufr-like representation. If the
1862!! conversion is not successful, the output variable is
1863!! set to \a vol7d_var_miss and the conversion function to \a
1864!! conv_func_miss.
1865FUNCTION vargrib2varbufr_convert(vargrib, c_func) RESULT(convert)
1866TYPE(volgrid6d_var),INTENT(in) :: vargrib !< input grib-like variable
1867TYPE(conv_func),INTENT(out),OPTIONAL :: c_func !< corresponding \a conv_func object
1868TYPE(vol7d_var) :: convert
1869
1870INTEGER :: i
1871
1872IF (.NOT. ALLOCATED(conv_fwd)) CALL vg6d_v7d_var_conv_setup()
1873
1874DO i = 1, SIZE(conv_fwd)
1875 IF (vargrib == conv_fwd(i)%vg6d_var) THEN
1876 convert = conv_fwd(i)%v7d_var
1877 IF (PRESENT(c_func)) c_func = conv_fwd(i)%c_func
1878 RETURN
1879 ENDIF
1880ENDDO
1881! not found
1882convert = vol7d_var_miss
1883IF (PRESENT(c_func)) c_func = conv_func_miss
1884
1885! set hint for backwards conversion
1886convert%gribhint(:) = (/vargrib%centre, vargrib%category, vargrib%number, &
1887 vargrib%discipline/)
1888
1889CALL l4f_log(l4f_warn, 'vargrib2varbufr: variable '// &
1890 trim(to_char(vargrib%centre))//':'//trim(to_char(vargrib%category))//':'// &
1891 trim(to_char(vargrib%number))//':'//trim(to_char(vargrib%discipline))// &
1892 ' not found in table')
1893
1894END FUNCTION vargrib2varbufr_convert
1895
1896
1897!> Convert a \a vol7d_var array object into a physically equivalent
1898!! \a volgrid6d_var array object. This method converts a bufr-like
1899!! array of physical variables \a vargrib, to an array of grib-like
1900!! variables \a varbufr. Unlike the opposite method \a
1901!! vargrib2varbufr, in this case the conversion is not uniqe and at
1902!! the moment the first matching grib-like variable is chosen, without
1903!! any control over the choice process. The output array must have
1904!! enough room for the converted variables. The method additionally
1905!! allocates a \a conv_func array object of the same size, which can
1906!! successively be used to convert the numerical values of the fields
1907!! associated to \a varbufr to the corresponding fields in the \a
1908!! grib-like representation. \a c_func will have to be deallocated by
1909!! the calling procedure. If a conversion is not successful, the
1910!! corresponding output variable is set to \a volgrid6d_var_miss and
1911!! the conversion function to \a conv_func_miss.
1912SUBROUTINE varbufr2vargrib(varbufr, vargrib, c_func, grid_id_template)
1913TYPE(vol7d_var),INTENT(in) :: varbufr(:) !< array of input bufr-like variables
1914TYPE(volgrid6d_var),INTENT(out) :: vargrib(:) !< array of output grib-like variables
1915TYPE(conv_func),POINTER :: c_func(:) !< pointer to an array of the corresponding \a conv_func objects, allocated in the method
1916TYPE(grid_id),INTENT(in),OPTIONAL :: grid_id_template !< a template (typically grib_api) to which data will be finally exported, it helps in improving variable conversion
1917
1918INTEGER :: i, n, stallo
1919
1920n = min(SIZE(varbufr), SIZE(vargrib))
1921ALLOCATE(c_func(n),stat=stallo)
1922IF (stallo /= 0) THEN
1923 CALL l4f_log(l4f_fatal,"allocating memory")
1924 CALL raise_fatal_error()
1925ENDIF
1926
1927DO i = 1, n
1928 vargrib(i) = convert(varbufr(i), c_func(i), grid_id_template)
1929ENDDO
1930
1931END SUBROUTINE varbufr2vargrib
1932
1933
1934!> Convert a \a vol7d_var object into a physically equivalent
1935!! \a volgrid6d_var object. This method returns a grib-like
1936!! representation of type \a volgrid6d_var of the bufr-like input
1937!! physical variable \a varbufr. Unlike the opposite \a convert
1938!! method, in this case the conversion is not uniqe and at the moment
1939!! the first matching grib-like variable is chosen, without any
1940!! control over the choice process. The method optionally returns a
1941!! \a conv_func object which can successively be used to convert the
1942!! numerical values of the field associated to \a varbufr to the
1943!! corresponding fields in the grib-like representation. If the
1944!! conversion is not successful, the output variable is set to \a
1945!! volgrid6d_var_miss and the conversion function to \a
1946!! conv_func_miss.
1947FUNCTION varbufr2vargrib_convert(varbufr, c_func, grid_id_template) RESULT(convert)
1948TYPE(vol7d_var),INTENT(in) :: varbufr !< input bufr-like variable
1949TYPE(conv_func),INTENT(out),OPTIONAL :: c_func !< corresponding \a conv_func object
1950TYPE(grid_id),INTENT(in),OPTIONAL :: grid_id_template !< a template (typically grib_api) to which data will be finally exported, it helps in improving variable conversion
1951TYPE(volgrid6d_var) :: convert
1952
1953INTEGER :: i
1954#ifdef HAVE_LIBGRIBAPI
1955INTEGER :: gaid, editionnumber, category, centre
1956#endif
1957
1958IF (.NOT. ALLOCATED(conv_bwd)) CALL vg6d_v7d_var_conv_setup()
1959
1960#ifdef HAVE_LIBGRIBAPI
1961editionnumber=255; category=255; centre=255
1962#endif
1963IF (PRESENT(grid_id_template)) THEN
1964#ifdef HAVE_LIBGRIBAPI
1965 gaid = grid_id_get_gaid(grid_id_template)
1966 IF (c_e(gaid)) THEN
1967 CALL grib_get(gaid, 'GRIBEditionNumber', editionnumber)
1968 IF (editionnumber == 1) THEN
1969 CALL grib_get(gaid,'gribTablesVersionNo',category)
1970 ENDIF
1971 CALL grib_get(gaid,'centre',centre)
1972 ENDIF
1973#endif
1974ENDIF
1975
1976DO i = 1, SIZE(conv_bwd)
1977 IF (varbufr == conv_bwd(i)%v7d_var) THEN
1978#ifdef HAVE_LIBGRIBAPI
1979 IF (editionnumber /= 255) THEN ! further check required (gaid present)
1980 IF (editionnumber == 1) THEN
1981 IF (conv_bwd(i)%vg6d_var%discipline /= 255) cycle ! wrong edition
1982 ELSE IF (editionnumber == 2) THEN
1983 IF (conv_bwd(i)%vg6d_var%discipline == 255) cycle ! wrong edition
1984 ENDIF
1985 IF (conv_bwd(i)%vg6d_var%centre /= 255 .AND. &
1986 conv_bwd(i)%vg6d_var%centre /= centre) cycle ! wrong centre
1987 ENDIF
1988#endif
1989 convert = conv_bwd(i)%vg6d_var
1990 IF (PRESENT(c_func)) c_func = conv_bwd(i)%c_func
1991 RETURN
1992 ENDIF
1993ENDDO
1994! not found
1995convert = volgrid6d_var_miss
1996IF (PRESENT(c_func)) c_func = conv_func_miss
1997
1998! if hint available use it as a fallback
1999IF (any(varbufr%gribhint /= imiss)) THEN
2000 convert%centre = varbufr%gribhint(1)
2001 convert%category = varbufr%gribhint(2)
2002 convert%number = varbufr%gribhint(3)
2003 convert%discipline = varbufr%gribhint(4)
2004ENDIF
2005
2006CALL l4f_log(l4f_warn, 'varbufr2vargrib: variable '// &
2007 trim(varbufr%btable)//" : "//trim(varbufr%description)//" : "//trim(varbufr%unit)// &
2008 ' not found in table')
2009
2010END FUNCTION varbufr2vargrib_convert
2011
2012
2013!> Normalize a variable definition converting it to the
2014!! format (grib edition) specified in the (grib) template provided.
2015!! This allows a basic grib1 <-> grib2 conversion provided that
2016!! entries for both grib editions of the related variable are present
2017!! in the static file \a vargrib2ufr.csv. If the \a c_func variable
2018!! returned is not missing (i.e. /= conv_func_miss) the field value
2019!! should be converted as well using the conv_func::compute method .
2020SUBROUTINE volgrid6d_var_normalize(this, c_func, grid_id_template)
2021TYPE(volgrid6d_var),INTENT(inout) :: this !< variable to normalize
2022TYPE(conv_func),INTENT(out) :: c_func !< \a conv_func object to convert data
2023TYPE(grid_id),INTENT(in) :: grid_id_template !< a template (typically grib_api) to which data will be finally exported, it helps in improving variable conversion
2024
2025LOGICAL :: eqed, eqcentre
2026INTEGER :: gaid, editionnumber, centre
2027TYPE(volgrid6d_var) :: tmpgrib
2028TYPE(vol7d_var) :: tmpbufr
2029TYPE(conv_func) tmpc_func1, tmpc_func2
2030
2031eqed = .true.
2032eqcentre = .true.
2033c_func = conv_func_miss
2034
2035#ifdef HAVE_LIBGRIBAPI
2036gaid = grid_id_get_gaid(grid_id_template)
2037IF (c_e(gaid)) THEN
2038 CALL grib_get(gaid, 'GRIBEditionNumber', editionnumber)
2039 CALL grib_get(gaid, 'centre', centre)
2040 eqed = editionnumber == 1 .EQV. this%discipline == 255
2041 eqcentre = centre == this%centre
2042ENDIF
2043#endif
2044
2045IF (eqed .AND. eqcentre) RETURN ! nothing to do
2046
2047tmpbufr = convert(this, tmpc_func1)
2048tmpgrib = convert(tmpbufr, tmpc_func2, grid_id_template)
2049
2050IF (tmpgrib /= volgrid6d_var_miss) THEN
2051! conversion back and forth successful, set also conversion function
2052 this = tmpgrib
2053 c_func = tmpc_func1 * tmpc_func2
2054! set to missing in common case to avoid useless computation
2055 IF (c_func == conv_func_identity) c_func = conv_func_miss
2056ELSE IF (.NOT.eqed) THEN
2057! conversion back and forth unsuccessful and grib edition incompatible, set to miss
2058 this = tmpgrib
2059ENDIF
2060
2061END SUBROUTINE volgrid6d_var_normalize
2062
2063
2064! Private subroutine for reading forward and backward conversion tables
2065! todo: better error handling
2066SUBROUTINE vg6d_v7d_var_conv_setup()
2067INTEGER :: un, i, n, stallo
2068
2069! forward, grib to bufr
2070un = open_package_file('vargrib2bufr.csv', filetype_data)
2071n=0
2072DO WHILE(.true.)
2073 READ(un,*,END=100)
2074 n = n + 1
2075ENDDO
2076
2077100 CONTINUE
2078
2079rewind(un)
2080ALLOCATE(conv_fwd(n),stat=stallo)
2081IF (stallo /= 0) THEN
2082 CALL l4f_log(l4f_fatal,"allocating memory")
2083 CALL raise_fatal_error()
2084ENDIF
2085
2086conv_fwd(:) = vg6d_v7d_var_conv_miss
2087CALL import_var_conv(un, conv_fwd)
2088CLOSE(un)
2089
2090! backward, bufr to grib
2091un = open_package_file('vargrib2bufr.csv', filetype_data)
2092! use the same file for now
2093!un = open_package_file('varbufr2grib.csv', filetype_data)
2094n=0
2095DO WHILE(.true.)
2096 READ(un,*,END=300)
2097 n = n + 1
2098ENDDO
2099
2100300 CONTINUE
2101
2102rewind(un)
2103ALLOCATE(conv_bwd(n),stat=stallo)
2104IF (stallo /= 0) THEN
2105 CALL l4f_log(l4f_fatal,"allocating memory")
2106 CALL raise_fatal_error()
2107end if
2108
2109conv_bwd(:) = vg6d_v7d_var_conv_miss
2110CALL import_var_conv(un, conv_bwd)
2111DO i = 1, n
2112 conv_bwd(i)%c_func%a = 1./conv_bwd(i)%c_func%a
2113 conv_bwd(i)%c_func%b = - conv_bwd(i)%c_func%b
2114ENDDO
2115CLOSE(un)
2116
2117CONTAINS
2118
2119SUBROUTINE import_var_conv(un, conv_type)
2120INTEGER, INTENT(in) :: un
2121TYPE(vg6d_v7d_var_conv), INTENT(out) :: conv_type(:)
2122
2123INTEGER :: i
2124TYPE(csv_record) :: csv
2125CHARACTER(len=1024) :: line
2126CHARACTER(len=10) :: btable
2127INTEGER :: centre, category, number, discipline
2128
2129DO i = 1, SIZE(conv_type)
2130 READ(un,'(A)',END=200)line
2131 CALL init(csv, line)
2132 CALL csv_record_getfield(csv, btable)
2133 CALL csv_record_getfield(csv) ! skip fields for description and unit,
2134 CALL csv_record_getfield(csv) ! they correspond to grib information, not bufr Btable
2135 CALL init(conv_type(i)%v7d_var, btable=btable)
2136
2137 CALL csv_record_getfield(csv, centre)
2138 CALL csv_record_getfield(csv, category)
2139 CALL csv_record_getfield(csv, number)
2140 CALL csv_record_getfield(csv, discipline)
2141 CALL init(conv_type(i)%vg6d_var, centre=centre, category=category, &
2142 number=number, discipline=discipline) ! controllare l'ordine
2143
2144 CALL csv_record_getfield(csv, conv_type(i)%c_func%a)
2145 CALL csv_record_getfield(csv, conv_type(i)%c_func%b)
2146 CALL delete(csv)
2147ENDDO
2148
2149200 CONTINUE
2150
2151END SUBROUTINE import_var_conv
2152
2153END SUBROUTINE vg6d_v7d_var_conv_setup
2154
2155
2156ELEMENTAL FUNCTION conv_func_eq(this, that) RESULT(res)
2157TYPE(conv_func),INTENT(IN) :: this, that
2158LOGICAL :: res
2159
2160res = this%a == that%a .AND. this%b == that%b
2161
2162END FUNCTION conv_func_eq
2163
2164
2165ELEMENTAL FUNCTION conv_func_ne(this, that) RESULT(res)
2166TYPE(conv_func),INTENT(IN) :: this, that
2167LOGICAL :: res
2168
2169res = .NOT.(this == that)
2170
2171END FUNCTION conv_func_ne
2172
2173
2174FUNCTION conv_func_mult(this, that) RESULT(mult)
2175TYPE(conv_func),INTENT(in) :: this
2176TYPE(conv_func),INTENT(in) :: that
2177
2178TYPE(conv_func) :: mult
2179
2180IF (this == conv_func_miss .OR. that == conv_func_miss) THEN
2181 mult = conv_func_miss
2182ELSE
2183 mult%a = this%a*that%a
2184 mult%b = this%a*that%b+this%b
2185ENDIF
2186
2187END FUNCTION conv_func_mult
2188
2189!> Apply the conversion function \a this to \a values.
2190!! The numerical conversion (only linear at the moment) defined by the
2191!! \a conv_func object \a this is applied to the \a values argument;
2192!! the converted result is stored in place; missing values remain
2193!! missing; if the conversion function is undefined (\a
2194!! conv_func_miss) the values are unchanged. The method is \c
2195!! ELEMENTAL, thus \a values can be also an array of any shape.
2196ELEMENTAL SUBROUTINE conv_func_compute(this, values)
2197TYPE(conv_func),INTENT(in) :: this !< object defining the conversion function
2198REAL,INTENT(inout) :: values !< value to be converted in place
2199
2200IF (this /= conv_func_miss) THEN
2201 IF (c_e(values)) values = values*this%a + this%b
2202ELSE
2203 values=rmiss
2204ENDIF
2205
2206END SUBROUTINE conv_func_compute
2207
2208
2209!> Locate variables which are horizontal components of a vector field.
2210!! This method scans the \a volgrid6d_var array provided and locates
2211!! pairs of variables which are x and y component of the same vector
2212!! field. On exit, the arrays \x xind(:) and \a yind(:) are allocated
2213!! to a size equal to the number of vector fields detected and their
2214!! corresponding elements will point to x and y components of the same
2215!! vector field. If inconsistencies are found, e.g. only one component
2216!! is detected for a field, or more than one input variable define
2217!! the same component, then \a xind and \a xind are nullified, thus an
2218!! error condition can be tested as \c .NOT.ASSOCIATED(xind). If no
2219!! vector fields are found then \a xind and \a xind are allocated to
2220!! zero size. If \a xind and \a yind are \c ASSOCIATED() after return,
2221!! they should be \c DEALLOCATEd by the calling procedure.
2222SUBROUTINE volgrid6d_var_hor_comp_index(this, xind, yind)
2223TYPE(volgrid6d_var),INTENT(in) :: this(:) !< array of volgrid6d_var objects (grib variable) to test
2224INTEGER,POINTER :: xind(:), yind(:) !< output arrays of indices pointing to matching horizontal components, allocated by this method
2225
2226TYPE(vol7d_var) :: varbufr(SIZE(this))
2227TYPE(conv_func),POINTER :: c_func(:)
2228INTEGER :: i, nv, counts(SIZE(vol7d_var_horcomp))
2229
2230NULLIFY(xind, yind)
2231counts(:) = 0
2232
2233CALL vargrib2varbufr(this, varbufr, c_func)
2234
2235DO i = 1, SIZE(vol7d_var_horcomp)
2236 counts(i) = count(varbufr(:) == vol7d_var_horcomp(i))
2237ENDDO
2238
2239IF (any(counts(1::2) > 1)) THEN
2240 CALL l4f_log(l4f_warn, '> 1 variable refer to x component of the same field, (un)rotation impossible')
2241 DEALLOCATE(c_func)
2242 RETURN
2243ENDIF
2244IF (any(counts(2::2) > 1)) THEN
2245 CALL l4f_log(l4f_warn, '> 1 variable refer to y component of the same field, (un)rotation impossible')
2246 DEALLOCATE(c_func)
2247 RETURN
2248ENDIF
2249
2250! check that variables are paired and count pairs
2251nv = 0
2252DO i = 1, SIZE(vol7d_var_horcomp), 2
2253 IF (counts(i) == 0 .AND. counts(i+1) > 0) THEN
2254 CALL l4f_log(l4f_warn, 'variable '//trim(vol7d_var_horcomp(i+1)%btable)// &
2255 ' present but the corresponding x-component '// &
2256 trim(vol7d_var_horcomp(i)%btable)//' is missing, (un)rotation impossible')
2257 RETURN
2258 ELSE IF (counts(i+1) == 0 .AND. counts(i) > 0) THEN
2259 CALL l4f_log(l4f_warn, 'variable '//trim(vol7d_var_horcomp(i)%btable)// &
2260 ' present but the corresponding y-component '// &
2261 trim(vol7d_var_horcomp(i+1)%btable)//' is missing, (un)rotation impossible')
2262 RETURN
2263 ENDIF
2264 IF (counts(i) == 1 .AND. counts(i+1) == 1) nv = nv + 1
2265ENDDO
2266
2267! repeat the loop storing indices
2268ALLOCATE(xind(nv), yind(nv))
2269nv = 0
2270DO i = 1, SIZE(vol7d_var_horcomp), 2
2271 IF (counts(i) == 1 .AND. counts(i+1) == 1) THEN
2272 nv = nv + 1
2273 xind(nv) = index(varbufr(:), vol7d_var_horcomp(i))
2274 yind(nv) = index(varbufr(:), vol7d_var_horcomp(i+1))
2275 ENDIF
2276ENDDO
2277DEALLOCATE(c_func)
2278
2279END SUBROUTINE volgrid6d_var_hor_comp_index
2280
2281
2282!> Tests whether a variable is the horizontal component of a vector field.
2283!! Returns \a .TRUE. if the corresponding variable is recognized as an
2284!! horizontal component of a vector field; if it is the case the
2285!! variable may need rotation in case of coordinate change.
2286FUNCTION volgrid6d_var_is_hor_comp(this) RESULT(is_hor_comp)
2287TYPE(volgrid6d_var),INTENT(in) :: this !< volgrid6d_var object (grib variable) to test
2288LOGICAL :: is_hor_comp
2289
2290TYPE(vol7d_var) :: varbufr
2291
2292varbufr = convert(this)
2293is_hor_comp = any(varbufr == vol7d_var_horcomp(:))
2294
2295END FUNCTION volgrid6d_var_is_hor_comp
2296
2297! before unstaggering??
2298
2299!IF (.NOT. ALLOCATED(conv_fwd)) CALL vg6d_v7d_var_conv_setup()
2300!
2301!call init(varu,btable="B11003")
2302!call init(varv,btable="B11004")
2303!
2304! test about presence of u and v in standard table
2305!if ( index(conv_fwd(:)%v7d_var,varu) == 0 .or. index(conv_fwd(:)%v7d_var,varv) == 0 )then
2306! call l4f_category_log(this%category,L4F_FATAL, &
2307! "variables B11003 and/or B11004 (wind components) not defined by vg6d_v7d_var_conv_setup")
2308! CALL raise_error()
2309! RETURN
2310!end if
2311!
2312!if (associated(this%var))then
2313! nvar=size(this%var)
2314! allocate(varbufr(nvar),stat=stallo)
2315! if (stallo /=0)then
2316! call l4f_log(L4F_FATAL,"allocating memory")
2317! call raise_fatal_error("allocating memory")
2318! end if
2319!
2320! CALL vargrib2varbufr(this%var, varbufr)
2321!ELSE
2322! CALL l4f_category_log(this%category, L4F_ERROR, &
2323! "trying to destagger an incomplete volgrid6d object")
2324! CALL raise_error()
2325! RETURN
2326!end if
2327!
2328!nvaru=COUNT(varbufr==varu)
2329!nvarv=COUNT(varbufr==varv)
2330!
2331!if (nvaru > 1 )then
2332! call l4f_category_log(this%category,L4F_WARN, &
2333! ">1 variables refer to u wind component, destaggering will not be done ")
2334! DEALLOCATE(varbufr)
2335! RETURN
2336!endif
2337!
2338!if (nvarv > 1 )then
2339! call l4f_category_log(this%category,L4F_WARN, &
2340! ">1 variables refer to v wind component, destaggering will not be done ")
2341! DEALLOCATE(varbufr)
2342! RETURN
2343!endif
2344!
2345!if (nvaru == 0 .and. nvarv == 0) then
2346! call l4f_category_log(this%category,L4F_WARN, &
2347! "no u or v wind component found in volume, nothing to do")
2348! DEALLOCATE(varbufr)
2349! RETURN
2350!endif
2351!
2352!if (COUNT(varbufr/=varu .and. varbufr/=varv) > 0) then
2353! call l4f_category_log(this%category,L4F_WARN, &
2354! "there are variables different from u and v wind component in C grid")
2355!endif
2356
2357
2358END MODULE volgrid6d_var_class
Index method.
Apply the conversion function this to values.
Apply the conversion function this to values.
Destructor for the corresponding object, it assigns it to a missing value.
Display on the screen a brief content of object.
Initialize a volgrid6d_var object with the optional arguments provided.
Gestione degli errori.
Utilities for managing files.
This module defines an abstract interface to different drivers for access to files containing gridded...
Definition of constants to be used for declaring variables of a desired type.
Definition kinds.F90:245
Definitions of constants and functions for working with missing values.
Classe per la gestione delle variabili osservate da stazioni meteo e affini.
Class for managing physical variables in a grib 1/2 fashion.
Definisce una variabile meteorologica osservata o un suo attributo.
Class defining a real conversion function between units.
Definition of a physical variable in grib coding style.

Generated with Doxygen.