libsim Versione 8.0.0

◆ volgrid6d_var_is_hor_comp()

logical function, public volgrid6d_var_is_hor_comp ( type(volgrid6d_var), intent(in) this)

Tests whether a variable is the horizontal component of a vector field.

Returns .TRUE. if the corresponding variable is recognized as an horizontal component of a vector field; if it is the case the variable may need rotation in case of coordinate change.

Parametri
[in]thisvolgrid6d_var object (grib variable) to test

Definizione alla linea 1544 del file volgrid6d_var_class.F90.

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