libsim Versione 8.0.0

◆ conv_func_compute()

elemental subroutine conv_func_compute ( type(conv_func), intent(in) this,
real, intent(inout) values )

Apply the conversion function this to values.

The numerical conversion (only linear at the moment) defined by the conv_func object this is applied to the values argument; the converted result is stored in place; missing values remain missing; if the conversion function is undefined (conv_func_miss) the values are unchanged. The method is ELEMENTAL, thus values can be also an array of any shape.

Parametri
[in]thisobject defining the conversion function
[in,out]valuesvalue to be converted in place

Definizione alla linea 1454 del file volgrid6d_var_class.F90.

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