|
libsim Versione 8.0.0
|
◆ volgrid6d_var_normalize()
Normalize a variable definition converting it to the format (grib edition) specified in the (grib) template provided. This allows a basic grib1 <-> grib2 conversion provided that entries for both grib editions of the related variable are present in the static file vargrib2ufr.csv. If the c_func variable returned is not missing (i.e. /= conv_func_miss) the field value should be converted as well using the conv_func::compute method .
Definizione alla linea 1278 del file volgrid6d_var_class.F90. 1279! Copyright (C) 2010 ARPA-SIM <urpsim@smr.arpa.emr.it>
1280! authors:
1281! Davide Cesari <dcesari@arpa.emr.it>
1282! Paolo Patruno <ppatruno@arpa.emr.it>
1283
1284! This program is free software; you can redistribute it and/or
1285! modify it under the terms of the GNU General Public License as
1286! published by the Free Software Foundation; either version 2 of
1287! the License, or (at your option) any later version.
1288
1289! This program is distributed in the hope that it will be useful,
1290! but WITHOUT ANY WARRANTY; without even the implied warranty of
1291! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1292! GNU General Public License for more details.
1293
1294! You should have received a copy of the GNU General Public License
1295! along with this program. If not, see <http://www.gnu.org/licenses/>.
1296#include "config.h"
1297
1298!> Class for managing physical variables in a grib 1/2 fashion.
1299!! This module defines a class which can represent Earth-science
1300!! related physical variables, following the classification scheme
1301!! adopted by WMO for grib1 and grib2 parameter definition. It also
1302!! defines some methods for mapping \a volgrid6d_var variables and
1303!! converting the corresponding fields to a matching \a vol7d_var
1304!! object defined in \a vol7d_var_class module, which, unlike the
1305!! variables defined here, defines univocally a physical quantity.
1306!!
1307!! \ingroup volgrid6d
1315
1316IMPLICIT NONE
1317
1318!> Definition of a physical variable in grib coding style.
1319!! \a volgrid6d_var members are public, thus they can be freely
1320!! altered, but it is advisable to set them through the
1321!! volgrid6d_var_class::init constructor.
1323 integer :: centre !< centre
1324 integer :: category !< grib2: category / grib1: grib table version number
1325 integer :: number !< parameter number
1326 integer :: discipline !< grib2: discipline / grib1: 255
1327 CHARACTER(len=65) :: description !< optional textual description of the variable
1328 CHARACTER(len=24) :: unit !< optional textual description of the variable's unit
1330
1331TYPE(volgrid6d_var),PARAMETER :: volgrid6d_var_miss= &
1333
1334TYPE(vol7d_var),PARAMETER :: vol7d_var_horstag(2) = (/ &
1337 /)
1338
1339TYPE(vol7d_var),PARAMETER :: vol7d_var_horcomp(4) = (/ &! RESHAPE( (/ &
1344/)
1345!/), (/2,2/)) ! bug in gfortran
1346
1347!> Class defining a real conversion function between units. It is
1348!! used to numerically convert a value expressed as a \a volgrid6d_var
1349!! variable in a value expressed as a \a vol7d_var variable and
1350!! vice-versa. At the moment only a linear conversion is
1351!! supported. Objects of this class are returned only by the \a
1352!! vargrib2varbufr \a varbufr2vargrib, and \a convert methods and are
1353!! used in the \a convert and \a compute methods defined in this
1354!! MODULE.
1356 PRIVATE
1357 REAL :: a, b
1359
1362
1363TYPE vg6d_v7d_var_conv
1364 TYPE(volgrid6d_var) :: vg6d_var
1365 TYPE(vol7d_var) :: v7d_var
1366 TYPE(conv_func) :: c_func
1367! aggiungere informazioni ad es. su rotazione del vento
1368END TYPE vg6d_v7d_var_conv
1369
1370TYPE(vg6d_v7d_var_conv), PARAMETER :: vg6d_v7d_var_conv_miss= &
1371 vg6d_v7d_var_conv(volgrid6d_var_miss, vol7d_var_miss, conv_func_miss)
1372
1373TYPE(vg6d_v7d_var_conv), ALLOCATABLE :: conv_fwd(:), conv_bwd(:)
1374
1375!> Initialize a \a volgrid6d_var object with the optional arguments provided.
1376!! If an argument is not provided, the corresponding object member and
1377!! those depending on it will be set to missing. For grib1-style
1378!! variables, the \a discipline argument must be omitted, it will be
1379!! set to 255 (grib missing value).
1380!!
1381!! \param this TYPE(volgrid6d_var),INTENT(INOUT) object to be initialized
1382!! \param centre INTEGER,INTENT(in),OPTIONAL centre
1383!! \param category INTEGER,INTENT(in),OPTIONAL grib2: category / grib1: grib table version number
1384!! \param number INTEGER,INTENT(in),OPTIONAL parameter number
1385!! \param discipline INTEGER,INTENT(in),OPTIONAL grib2: discipline / grib1: 255
1386!! \param description CHARACTER(len=*),INTENT(in),OPTIONAL optional textual description of the variable
1387!! \param unit CHARACTER(len=*),INTENT(in),OPTIONAL optional textual description of the variable's unit
1389 MODULE PROCEDURE volgrid6d_var_init
1390END INTERFACE
1391
1392!> Destructor for the corresponding object, it assigns it to a missing value.
1393!! \param this TYPE(volgrid6d_var) object to be destroyed
1395 MODULE PROCEDURE volgrid6d_var_delete
1396END INTERFACE
1397
1398INTERFACE c_e
1399 MODULE PROCEDURE volgrid6d_var_c_e
1400END INTERFACE
1401
1402
1403!> Logical equality operators for objects of the classes \a
1404!! volgrid6d_var and \a conv_func.
1405!! They are all defined as \c ELEMENTAL thus work also on arrays of
1406!! any shape.
1407INTERFACE OPERATOR (==)
1408 MODULE PROCEDURE volgrid6d_var_eq, conv_func_eq
1409END INTERFACE
1410
1411!> Logical inequality operators for objects of the classes \a
1412!! volgrid6d_var and \a conv_func.
1413!! They are all defined as \c ELEMENTAL thus work also on arrays of
1414!! any shape.
1415INTERFACE OPERATOR (/=)
1416 MODULE PROCEDURE volgrid6d_var_ne, conv_func_ne
1417END INTERFACE
1418
1419#define VOL7D_POLY_TYPE TYPE(volgrid6d_var)
1420#define VOL7D_POLY_TYPES _var6d
1421#include "array_utilities_pre.F90"
1422
1423!> Display on the screen a brief content of object
1425 MODULE PROCEDURE display_volgrid6d_var
1426END INTERFACE
1427
1428!> Compose two conversions into a single one.
1429!! Unlike scalar multiplication (and like matrix multiplication) here
1430!! a*b /= b*a. By convention, the second factor is applied first in
1431!! the result.
1432INTERFACE OPERATOR (*)
1433 MODULE PROCEDURE conv_func_mult
1434END INTERFACE OPERATOR (*)
1435
1436!> Apply the conversion function \a this to \a values.
1437!! function version
1439 MODULE PROCEDURE conv_func_compute
1440END INTERFACE
1441
1442!> Apply the conversion function \a this to \a values.
1443!! subroutine version
1445 MODULE PROCEDURE varbufr2vargrib_convert, vargrib2varbufr_convert
1446END INTERFACE
1447
1448PRIVATE
1450 c_e, volgrid6d_var_normalize, &
1451 OPERATOR(==), OPERATOR(/=), OPERATOR(*), &
1452 count_distinct, pack_distinct, count_and_pack_distinct, &
1453 map_distinct, map_inv_distinct, &
1455 vargrib2varbufr, varbufr2vargrib, &
1457 volgrid6d_var_hor_comp_index, volgrid6d_var_is_hor_comp
1458
1459
1460CONTAINS
1461
1462
1463ELEMENTAL FUNCTION volgrid6d_var_new(centre, category, number, &
1464 discipline, description, unit) RESULT(this)
1465integer,INTENT(in),OPTIONAL :: centre !< centre
1466integer,INTENT(in),OPTIONAL :: category !< grib2: category / grib1: grib table version number
1467integer,INTENT(in),OPTIONAL :: number !< parameter number
1468integer,INTENT(in),OPTIONAL :: discipline !< grib2: discipline
1469CHARACTER(len=*),INTENT(in),OPTIONAL :: description !< textual description of the variable
1470CHARACTER(len=*),INTENT(in),OPTIONAL :: unit !< textual description of the variable's unit
1471
1472TYPE(volgrid6d_var) :: this !< object to be initialised
1473
1475
1476END FUNCTION volgrid6d_var_new
1477
1478
1479! documented in the interface
1480ELEMENTAL SUBROUTINE volgrid6d_var_init(this, centre, category, number, discipline,description,unit)
1481TYPE(volgrid6d_var),INTENT(INOUT) :: this ! object to be initialized
1482INTEGER,INTENT(in),OPTIONAL :: centre ! centre
1483INTEGER,INTENT(in),OPTIONAL :: category ! grib2: category / grib1: grib table version number
1484INTEGER,INTENT(in),OPTIONAL :: number ! parameter number
1485INTEGER,INTENT(in),OPTIONAL :: discipline ! grib2: discipline / grib1: 255
1486CHARACTER(len=*),INTENT(in),OPTIONAL :: description ! optional textual description of the variable
1487CHARACTER(len=*),INTENT(in),OPTIONAL :: unit ! optional textual description of the variable's unit
1488
1489IF (PRESENT(centre)) THEN
1490 this%centre = centre
1491ELSE
1492 this%centre = imiss
1493 this%category = imiss
1494 this%number = imiss
1495 this%discipline = imiss
1496 RETURN
1497ENDIF
1498
1499IF (PRESENT(category)) THEN
1500 this%category = category
1501ELSE
1502 this%category = imiss
1503 this%number = imiss
1504 this%discipline = imiss
1505 RETURN
1506ENDIF
1507
1508
1509IF (PRESENT(number)) THEN
1510 this%number = number
1511ELSE
1512 this%number = imiss
1513 this%discipline = imiss
1514 RETURN
1515ENDIF
1516
1517! se sono arrivato fino a qui ho impostato centre, category e number
1518!per il grib 1 manca discipline e imposto 255 (missing del grib2)
1519
1520IF (PRESENT(discipline)) THEN
1521 this%discipline = discipline
1522ELSE
1523 this%discipline = 255
1524ENDIF
1525
1526IF (PRESENT(description)) THEN
1527 this%description = description
1528ELSE
1529 this%description = cmiss
1530ENDIF
1531
1532IF (PRESENT(unit)) THEN
1533 this%unit = unit
1534ELSE
1535 this%unit = cmiss
1536ENDIF
1537
1538
1539
1540END SUBROUTINE volgrid6d_var_init
1541
1542
1543! documented in the interface
1544SUBROUTINE volgrid6d_var_delete(this)
1545TYPE(volgrid6d_var),INTENT(INOUT) :: this
1546
1547this%centre = imiss
1548this%category = imiss
1549this%number = imiss
1550this%discipline = imiss
1551this%description = cmiss
1552this%unit = cmiss
1553
1554END SUBROUTINE volgrid6d_var_delete
1555
1556
1557ELEMENTAL FUNCTION volgrid6d_var_c_e(this) RESULT(c_e)
1558TYPE(volgrid6d_var),INTENT(IN) :: this
1559LOGICAL :: c_e
1560c_e = this /= volgrid6d_var_miss
1561END FUNCTION volgrid6d_var_c_e
1562
1563
1564ELEMENTAL FUNCTION volgrid6d_var_eq(this, that) RESULT(res)
1565TYPE(volgrid6d_var),INTENT(IN) :: this, that
1566LOGICAL :: res
1567
1568IF (this%discipline == that%discipline) THEN
1569
1570 IF (this%discipline == 255) THEN ! grib1, WMO tables are all equivalent
1571 res = ((this%category == that%category) .OR. &
1572 (this%category >= 1 .AND. this%category <=3 .AND. &
1573 that%category >= 1 .AND. that%category <=3)) .AND. &
1574 this%number == that%number
1575
1576 IF ((this%category >= 128 .AND. this%category <= 254) .OR. &
1577 (this%number >= 128 .AND. this%number <= 254)) THEN
1578 res = res .AND. this%centre == that%centre ! local definition, centre matters
1579 ENDIF
1580
1581 ELSE ! grib2
1582 res = this%category == that%category .AND. &
1583 this%number == that%number
1584
1585 IF ((this%discipline >= 192 .AND. this%discipline <= 254) .OR. &
1586 (this%category >= 192 .AND. this%category <= 254) .OR. &
1587 (this%number >= 192 .AND. this%number <= 254)) THEN
1588 res = res .AND. this%centre == that%centre ! local definition, centre matters
1589 ENDIF
1590 ENDIF
1591
1592ELSE ! different edition or different discipline
1593 res = .false.
1594ENDIF
1595
1596END FUNCTION volgrid6d_var_eq
1597
1598
1599ELEMENTAL FUNCTION volgrid6d_var_ne(this, that) RESULT(res)
1600TYPE(volgrid6d_var),INTENT(IN) :: this, that
1601LOGICAL :: res
1602
1603res = .NOT.(this == that)
1604
1605END FUNCTION volgrid6d_var_ne
1606
1607
1608#include "array_utilities_inc.F90"
1609
1610
1611!> Display on the screen a brief content of \a volgrid6d_var object.
1612SUBROUTINE display_volgrid6d_var(this)
1613TYPE(volgrid6d_var),INTENT(in) :: this !< volgrid6d_var object to display
1614
1615print*,"GRIDVAR: ",this%centre,this%discipline,this%category,this%number
1616
1617END SUBROUTINE display_volgrid6d_var
1618
1619
1620!> Convert a \a volgrid6d_var array object into a physically equivalent
1621!! \a vol7d_var array object. This method converts a grib-like array
1622!! of physical variables \a vargrib, to an array of unique, physically
1623!! based, bufr-like variables \a varbufr. The output array must have
1624!! enough room for the converted variables. The method additionally
1625!! allocates a \a conv_func array object of the same size, which can
1626!! successively be used to convert the numerical values of the fields
1627!! associated to \a vargrib to the corresponding fields in the \a
1628!! bufr-like representation. \a c_func will have to be deallocated by
1629!! the calling procedure. If a conversion is not successful, the
1630!! corresponding output variable is set to \a vol7d_var_miss and the
1631!! conversion function to \a conv_func_miss.
1632SUBROUTINE vargrib2varbufr(vargrib, varbufr, c_func)
1633TYPE(volgrid6d_var),INTENT(in) :: vargrib(:) !< array of input grib-like variables
1634TYPE(vol7d_var),INTENT(out) :: varbufr(:) !< array of output bufr-like variables
1635TYPE(conv_func),POINTER :: c_func(:) !< pointer to an array of the corresponding \a conv_func objects, allocated in the method
1636
1637INTEGER :: i, n, stallo
1638
1639n = min(SIZE(varbufr), SIZE(vargrib))
1640ALLOCATE(c_func(n),stat=stallo)
1641IF (stallo /= 0) THEN
1642 call l4f_log(l4f_fatal,"allocating memory")
1643 call raise_fatal_error()
1644ENDIF
1645
1646DO i = 1, n
1647 varbufr(i) = convert(vargrib(i), c_func(i))
1648ENDDO
1649
1650END SUBROUTINE vargrib2varbufr
1651
1652
1653!> Convert a \a volgrid6d_var object into a physically equivalent
1654!! \a vol7d_var object. This method returns a physically based,
1655!! bufr-like representation of type \a vol7d_var of the grib-like
1656!! input physical variable \a vargrib. The method optionally returns
1657!! a \a conv_func object which can successively be used to convert the
1658!! numerical values of the field associated to \a vargrib to the
1659!! corresponding fields in the bufr-like representation. If the
1660!! conversion is not successful, the output variable is
1661!! set to \a vol7d_var_miss and the conversion function to \a
1662!! conv_func_miss.
1663FUNCTION vargrib2varbufr_convert(vargrib, c_func) RESULT(convert)
1664TYPE(volgrid6d_var),INTENT(in) :: vargrib !< input grib-like variable
1665TYPE(conv_func),INTENT(out),OPTIONAL :: c_func !< corresponding \a conv_func object
1666TYPE(vol7d_var) :: convert
1667
1668INTEGER :: i
1669
1670IF (.NOT. ALLOCATED(conv_fwd)) CALL vg6d_v7d_var_conv_setup()
1671
1672DO i = 1, SIZE(conv_fwd)
1673 IF (vargrib == conv_fwd(i)%vg6d_var) THEN
1674 convert = conv_fwd(i)%v7d_var
1675 IF (PRESENT(c_func)) c_func = conv_fwd(i)%c_func
1676 RETURN
1677 ENDIF
1678ENDDO
1679! not found
1680convert = vol7d_var_miss
1681IF (PRESENT(c_func)) c_func = conv_func_miss
1682
1683! set hint for backwards conversion
1684convert%gribhint(:) = (/vargrib%centre, vargrib%category, vargrib%number, &
1685 vargrib%discipline/)
1686
1687CALL l4f_log(l4f_warn, 'vargrib2varbufr: variable '// &
1688 trim(to_char(vargrib%centre))//':'//trim(to_char(vargrib%category))//':'// &
1689 trim(to_char(vargrib%number))//':'//trim(to_char(vargrib%discipline))// &
1690 ' not found in table')
1691
1692END FUNCTION vargrib2varbufr_convert
1693
1694
1695!> Convert a \a vol7d_var array object into a physically equivalent
1696!! \a volgrid6d_var array object. This method converts a bufr-like
1697!! array of physical variables \a vargrib, to an array of grib-like
1698!! variables \a varbufr. Unlike the opposite method \a
1699!! vargrib2varbufr, in this case the conversion is not uniqe and at
1700!! the moment the first matching grib-like variable is chosen, without
1701!! any control over the choice process. The output array must have
1702!! enough room for the converted variables. The method additionally
1703!! allocates a \a conv_func array object of the same size, which can
1704!! successively be used to convert the numerical values of the fields
1705!! associated to \a varbufr to the corresponding fields in the \a
1706!! grib-like representation. \a c_func will have to be deallocated by
1707!! the calling procedure. If a conversion is not successful, the
1708!! corresponding output variable is set to \a volgrid6d_var_miss and
1709!! the conversion function to \a conv_func_miss.
1710SUBROUTINE varbufr2vargrib(varbufr, vargrib, c_func, grid_id_template)
1711TYPE(vol7d_var),INTENT(in) :: varbufr(:) !< array of input bufr-like variables
1712TYPE(volgrid6d_var),INTENT(out) :: vargrib(:) !< array of output grib-like variables
1713TYPE(conv_func),POINTER :: c_func(:) !< pointer to an array of the corresponding \a conv_func objects, allocated in the method
1714TYPE(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
1715
1716INTEGER :: i, n, stallo
1717
1718n = min(SIZE(varbufr), SIZE(vargrib))
1719ALLOCATE(c_func(n),stat=stallo)
1720IF (stallo /= 0) THEN
1721 CALL l4f_log(l4f_fatal,"allocating memory")
1722 CALL raise_fatal_error()
1723ENDIF
1724
1725DO i = 1, n
1726 vargrib(i) = convert(varbufr(i), c_func(i), grid_id_template)
1727ENDDO
1728
1729END SUBROUTINE varbufr2vargrib
1730
1731
1732!> Convert a \a vol7d_var object into a physically equivalent
1733!! \a volgrid6d_var object. This method returns a grib-like
1734!! representation of type \a volgrid6d_var of the bufr-like input
1735!! physical variable \a varbufr. Unlike the opposite \a convert
1736!! method, in this case the conversion is not uniqe and at the moment
1737!! the first matching grib-like variable is chosen, without any
1738!! control over the choice process. The method optionally returns a
1739!! \a conv_func object which can successively be used to convert the
1740!! numerical values of the field associated to \a varbufr to the
1741!! corresponding fields in the grib-like representation. If the
1742!! conversion is not successful, the output variable is set to \a
1743!! volgrid6d_var_miss and the conversion function to \a
1744!! conv_func_miss.
1745FUNCTION varbufr2vargrib_convert(varbufr, c_func, grid_id_template) RESULT(convert)
1746TYPE(vol7d_var),INTENT(in) :: varbufr !< input bufr-like variable
1747TYPE(conv_func),INTENT(out),OPTIONAL :: c_func !< corresponding \a conv_func object
1748TYPE(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
1749TYPE(volgrid6d_var) :: convert
1750
1751INTEGER :: i
1752#ifdef HAVE_LIBGRIBAPI
1753INTEGER :: gaid, editionnumber, category, centre
1754#endif
1755
1756IF (.NOT. ALLOCATED(conv_bwd)) CALL vg6d_v7d_var_conv_setup()
1757
1758#ifdef HAVE_LIBGRIBAPI
1759editionnumber=255; category=255; centre=255
1760#endif
1761IF (PRESENT(grid_id_template)) THEN
1762#ifdef HAVE_LIBGRIBAPI
1763 gaid = grid_id_get_gaid(grid_id_template)
1764 IF (c_e(gaid)) THEN
1765 CALL grib_get(gaid, 'GRIBEditionNumber', editionnumber)
1766 IF (editionnumber == 1) THEN
1767 CALL grib_get(gaid,'gribTablesVersionNo',category)
1768 ENDIF
1769 CALL grib_get(gaid,'centre',centre)
1770 ENDIF
1771#endif
1772ENDIF
1773
1774DO i = 1, SIZE(conv_bwd)
1775 IF (varbufr == conv_bwd(i)%v7d_var) THEN
1776#ifdef HAVE_LIBGRIBAPI
1777 IF (editionnumber /= 255) THEN ! further check required (gaid present)
1778 IF (editionnumber == 1) THEN
1779 IF (conv_bwd(i)%vg6d_var%discipline /= 255) cycle ! wrong edition
1780 ELSE IF (editionnumber == 2) THEN
1781 IF (conv_bwd(i)%vg6d_var%discipline == 255) cycle ! wrong edition
1782 ENDIF
1783 IF (conv_bwd(i)%vg6d_var%centre /= 255 .AND. &
1784 conv_bwd(i)%vg6d_var%centre /= centre) cycle ! wrong centre
1785 ENDIF
1786#endif
1787 convert = conv_bwd(i)%vg6d_var
1788 IF (PRESENT(c_func)) c_func = conv_bwd(i)%c_func
1789 RETURN
1790 ENDIF
1791ENDDO
1792! not found
1793convert = volgrid6d_var_miss
1794IF (PRESENT(c_func)) c_func = conv_func_miss
1795
1796! if hint available use it as a fallback
1797IF (any(varbufr%gribhint /= imiss)) THEN
1798 convert%centre = varbufr%gribhint(1)
1799 convert%category = varbufr%gribhint(2)
1800 convert%number = varbufr%gribhint(3)
1801 convert%discipline = varbufr%gribhint(4)
1802ENDIF
1803
1804CALL l4f_log(l4f_warn, 'varbufr2vargrib: variable '// &
1805 trim(varbufr%btable)//" : "//trim(varbufr%description)//" : "//trim(varbufr%unit)// &
1806 ' not found in table')
1807
1808END FUNCTION varbufr2vargrib_convert
1809
1810
1811!> Normalize a variable definition converting it to the
1812!! format (grib edition) specified in the (grib) template provided.
1813!! This allows a basic grib1 <-> grib2 conversion provided that
1814!! entries for both grib editions of the related variable are present
1815!! in the static file \a vargrib2ufr.csv. If the \a c_func variable
1816!! returned is not missing (i.e. /= conv_func_miss) the field value
1817!! should be converted as well using the conv_func::compute method .
1818SUBROUTINE volgrid6d_var_normalize(this, c_func, grid_id_template)
1819TYPE(volgrid6d_var),INTENT(inout) :: this !< variable to normalize
1820TYPE(conv_func),INTENT(out) :: c_func !< \a conv_func object to convert data
1821TYPE(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
1822
1823LOGICAL :: eqed, eqcentre
1824INTEGER :: gaid, editionnumber, centre
1825TYPE(volgrid6d_var) :: tmpgrib
1826TYPE(vol7d_var) :: tmpbufr
1827TYPE(conv_func) tmpc_func1, tmpc_func2
1828
1829eqed = .true.
1830eqcentre = .true.
1831c_func = conv_func_miss
1832
1833#ifdef HAVE_LIBGRIBAPI
1834gaid = grid_id_get_gaid(grid_id_template)
1835IF (c_e(gaid)) THEN
1836 CALL grib_get(gaid, 'GRIBEditionNumber', editionnumber)
1837 CALL grib_get(gaid, 'centre', centre)
1838 eqed = editionnumber == 1 .EQV. this%discipline == 255
1839 eqcentre = centre == this%centre
1840ENDIF
1841#endif
1842
1843IF (eqed .AND. eqcentre) RETURN ! nothing to do
1844
1845tmpbufr = convert(this, tmpc_func1)
1846tmpgrib = convert(tmpbufr, tmpc_func2, grid_id_template)
1847
1848IF (tmpgrib /= volgrid6d_var_miss) THEN
1849! conversion back and forth successful, set also conversion function
1850 this = tmpgrib
1851 c_func = tmpc_func1 * tmpc_func2
1852! set to missing in common case to avoid useless computation
1853 IF (c_func == conv_func_identity) c_func = conv_func_miss
1854ELSE IF (.NOT.eqed) THEN
1855! conversion back and forth unsuccessful and grib edition incompatible, set to miss
1856 this = tmpgrib
1857ENDIF
1858
1859END SUBROUTINE volgrid6d_var_normalize
1860
1861
1862! Private subroutine for reading forward and backward conversion tables
1863! todo: better error handling
1864SUBROUTINE vg6d_v7d_var_conv_setup()
1865INTEGER :: un, i, n, stallo
1866
1867! forward, grib to bufr
1868un = open_package_file('vargrib2bufr.csv', filetype_data)
1869n=0
1870DO WHILE(.true.)
1871 READ(un,*,END=100)
1872 n = n + 1
1873ENDDO
1874
1875100 CONTINUE
1876
1877rewind(un)
1878ALLOCATE(conv_fwd(n),stat=stallo)
1879IF (stallo /= 0) THEN
1880 CALL l4f_log(l4f_fatal,"allocating memory")
1881 CALL raise_fatal_error()
1882ENDIF
1883
1884conv_fwd(:) = vg6d_v7d_var_conv_miss
1885CALL import_var_conv(un, conv_fwd)
1886CLOSE(un)
1887
1888! backward, bufr to grib
1889un = open_package_file('vargrib2bufr.csv', filetype_data)
1890! use the same file for now
1891!un = open_package_file('varbufr2grib.csv', filetype_data)
1892n=0
1893DO WHILE(.true.)
1894 READ(un,*,END=300)
1895 n = n + 1
1896ENDDO
1897
1898300 CONTINUE
1899
1900rewind(un)
1901ALLOCATE(conv_bwd(n),stat=stallo)
1902IF (stallo /= 0) THEN
1903 CALL l4f_log(l4f_fatal,"allocating memory")
1904 CALL raise_fatal_error()
1905end if
1906
1907conv_bwd(:) = vg6d_v7d_var_conv_miss
1908CALL import_var_conv(un, conv_bwd)
1909DO i = 1, n
1910 conv_bwd(i)%c_func%a = 1./conv_bwd(i)%c_func%a
1911 conv_bwd(i)%c_func%b = - conv_bwd(i)%c_func%b
1912ENDDO
1913CLOSE(un)
1914
1915CONTAINS
1916
1917SUBROUTINE import_var_conv(un, conv_type)
1918INTEGER, INTENT(in) :: un
1919TYPE(vg6d_v7d_var_conv), INTENT(out) :: conv_type(:)
1920
1921INTEGER :: i
1922TYPE(csv_record) :: csv
1923CHARACTER(len=1024) :: line
1924CHARACTER(len=10) :: btable
1925INTEGER :: centre, category, number, discipline
1926
1927DO i = 1, SIZE(conv_type)
1928 READ(un,'(A)',END=200)line
1930 CALL csv_record_getfield(csv, btable)
1931 CALL csv_record_getfield(csv) ! skip fields for description and unit,
1932 CALL csv_record_getfield(csv) ! they correspond to grib information, not bufr Btable
1934
1935 CALL csv_record_getfield(csv, centre)
1936 CALL csv_record_getfield(csv, category)
1937 CALL csv_record_getfield(csv, number)
1938 CALL csv_record_getfield(csv, discipline)
1940 number=number, discipline=discipline) ! controllare l'ordine
1941
1942 CALL csv_record_getfield(csv, conv_type(i)%c_func%a)
1943 CALL csv_record_getfield(csv, conv_type(i)%c_func%b)
1945ENDDO
1946
1947200 CONTINUE
1948
1949END SUBROUTINE import_var_conv
1950
1951END SUBROUTINE vg6d_v7d_var_conv_setup
1952
1953
1954ELEMENTAL FUNCTION conv_func_eq(this, that) RESULT(res)
1955TYPE(conv_func),INTENT(IN) :: this, that
1956LOGICAL :: res
1957
1958res = this%a == that%a .AND. this%b == that%b
1959
1960END FUNCTION conv_func_eq
1961
1962
1963ELEMENTAL FUNCTION conv_func_ne(this, that) RESULT(res)
1964TYPE(conv_func),INTENT(IN) :: this, that
1965LOGICAL :: res
1966
1967res = .NOT.(this == that)
1968
1969END FUNCTION conv_func_ne
1970
1971
1972FUNCTION conv_func_mult(this, that) RESULT(mult)
1973TYPE(conv_func),INTENT(in) :: this
1974TYPE(conv_func),INTENT(in) :: that
1975
1976TYPE(conv_func) :: mult
1977
1978IF (this == conv_func_miss .OR. that == conv_func_miss) THEN
1979 mult = conv_func_miss
1980ELSE
1981 mult%a = this%a*that%a
1982 mult%b = this%a*that%b+this%b
1983ENDIF
1984
1985END FUNCTION conv_func_mult
1986
1987!> Apply the conversion function \a this to \a values.
1988!! The numerical conversion (only linear at the moment) defined by the
1989!! \a conv_func object \a this is applied to the \a values argument;
1990!! the converted result is stored in place; missing values remain
1991!! missing; if the conversion function is undefined (\a
1992!! conv_func_miss) the values are unchanged. The method is \c
1993!! ELEMENTAL, thus \a values can be also an array of any shape.
1994ELEMENTAL SUBROUTINE conv_func_compute(this, values)
1995TYPE(conv_func),INTENT(in) :: this !< object defining the conversion function
1996REAL,INTENT(inout) :: values !< value to be converted in place
1997
1998IF (this /= conv_func_miss) THEN
1999 IF (c_e(values)) values = values*this%a + this%b
2000ELSE
2001 values=rmiss
2002ENDIF
2003
2004END SUBROUTINE conv_func_compute
2005
2006
2007!> Locate variables which are horizontal components of a vector field.
2008!! This method scans the \a volgrid6d_var array provided and locates
2009!! pairs of variables which are x and y component of the same vector
2010!! field. On exit, the arrays \x xind(:) and \a yind(:) are allocated
2011!! to a size equal to the number of vector fields detected and their
2012!! corresponding elements will point to x and y components of the same
2013!! vector field. If inconsistencies are found, e.g. only one component
2014!! is detected for a field, or more than one input variable define
2015!! the same component, then \a xind and \a xind are nullified, thus an
2016!! error condition can be tested as \c .NOT.ASSOCIATED(xind). If no
2017!! vector fields are found then \a xind and \a xind are allocated to
2018!! zero size. If \a xind and \a yind are \c ASSOCIATED() after return,
2019!! they should be \c DEALLOCATEd by the calling procedure.
2020SUBROUTINE volgrid6d_var_hor_comp_index(this, xind, yind)
2021TYPE(volgrid6d_var),INTENT(in) :: this(:) !< array of volgrid6d_var objects (grib variable) to test
2022INTEGER,POINTER :: xind(:), yind(:) !< output arrays of indices pointing to matching horizontal components, allocated by this method
2023
2024TYPE(vol7d_var) :: varbufr(SIZE(this))
2025TYPE(conv_func),POINTER :: c_func(:)
2026INTEGER :: i, nv, counts(SIZE(vol7d_var_horcomp))
2027
2028NULLIFY(xind, yind)
2029counts(:) = 0
2030
2031CALL vargrib2varbufr(this, varbufr, c_func)
2032
2033DO i = 1, SIZE(vol7d_var_horcomp)
2034 counts(i) = count(varbufr(:) == vol7d_var_horcomp(i))
2035ENDDO
2036
2037IF (any(counts(1::2) > 1)) THEN
2038 CALL l4f_log(l4f_warn, '> 1 variable refer to x component of the same field, (un)rotation impossible')
2039 DEALLOCATE(c_func)
2040 RETURN
2041ENDIF
2042IF (any(counts(2::2) > 1)) THEN
2043 CALL l4f_log(l4f_warn, '> 1 variable refer to y component of the same field, (un)rotation impossible')
2044 DEALLOCATE(c_func)
2045 RETURN
2046ENDIF
2047
2048! check that variables are paired and count pairs
2049nv = 0
2050DO i = 1, SIZE(vol7d_var_horcomp), 2
2051 IF (counts(i) == 0 .AND. counts(i+1) > 0) THEN
2052 CALL l4f_log(l4f_warn, 'variable '//trim(vol7d_var_horcomp(i+1)%btable)// &
2053 ' present but the corresponding x-component '// &
2054 trim(vol7d_var_horcomp(i)%btable)//' is missing, (un)rotation impossible')
2055 RETURN
2056 ELSE IF (counts(i+1) == 0 .AND. counts(i) > 0) THEN
2057 CALL l4f_log(l4f_warn, 'variable '//trim(vol7d_var_horcomp(i)%btable)// &
2058 ' present but the corresponding y-component '// &
2059 trim(vol7d_var_horcomp(i+1)%btable)//' is missing, (un)rotation impossible')
2060 RETURN
2061 ENDIF
2062 IF (counts(i) == 1 .AND. counts(i+1) == 1) nv = nv + 1
2063ENDDO
2064
2065! repeat the loop storing indices
2066ALLOCATE(xind(nv), yind(nv))
2067nv = 0
2068DO i = 1, SIZE(vol7d_var_horcomp), 2
2069 IF (counts(i) == 1 .AND. counts(i+1) == 1) THEN
2070 nv = nv + 1
2071 xind(nv) = index(varbufr(:), vol7d_var_horcomp(i))
2072 yind(nv) = index(varbufr(:), vol7d_var_horcomp(i+1))
2073 ENDIF
2074ENDDO
2075DEALLOCATE(c_func)
2076
2077END SUBROUTINE volgrid6d_var_hor_comp_index
2078
2079
2080!> Tests whether a variable is the horizontal component of a vector field.
2081!! Returns \a .TRUE. if the corresponding variable is recognized as an
2082!! horizontal component of a vector field; if it is the case the
2083!! variable may need rotation in case of coordinate change.
2084FUNCTION volgrid6d_var_is_hor_comp(this) RESULT(is_hor_comp)
2085TYPE(volgrid6d_var),INTENT(in) :: this !< volgrid6d_var object (grib variable) to test
2086LOGICAL :: is_hor_comp
2087
2088TYPE(vol7d_var) :: varbufr
2089
2090varbufr = convert(this)
2091is_hor_comp = any(varbufr == vol7d_var_horcomp(:))
2092
2093END FUNCTION volgrid6d_var_is_hor_comp
2094
2095! before unstaggering??
2096
2097!IF (.NOT. ALLOCATED(conv_fwd)) CALL vg6d_v7d_var_conv_setup()
2098!
2099!call init(varu,btable="B11003")
2100!call init(varv,btable="B11004")
2101!
2102! test about presence of u and v in standard table
2103!if ( index(conv_fwd(:)%v7d_var,varu) == 0 .or. index(conv_fwd(:)%v7d_var,varv) == 0 )then
2104! call l4f_category_log(this%category,L4F_FATAL, &
2105! "variables B11003 and/or B11004 (wind components) not defined by vg6d_v7d_var_conv_setup")
2106! CALL raise_error()
2107! RETURN
2108!end if
2109!
2110!if (associated(this%var))then
2111! nvar=size(this%var)
2112! allocate(varbufr(nvar),stat=stallo)
2113! if (stallo /=0)then
2114! call l4f_log(L4F_FATAL,"allocating memory")
2115! call raise_fatal_error("allocating memory")
2116! end if
2117!
2118! CALL vargrib2varbufr(this%var, varbufr)
2119!ELSE
2120! CALL l4f_category_log(this%category, L4F_ERROR, &
2121! "trying to destagger an incomplete volgrid6d object")
2122! CALL raise_error()
2123! RETURN
2124!end if
2125!
2126!nvaru=COUNT(varbufr==varu)
2127!nvarv=COUNT(varbufr==varv)
2128!
2129!if (nvaru > 1 )then
2130! call l4f_category_log(this%category,L4F_WARN, &
2131! ">1 variables refer to u wind component, destaggering will not be done ")
2132! DEALLOCATE(varbufr)
2133! RETURN
2134!endif
2135!
2136!if (nvarv > 1 )then
2137! call l4f_category_log(this%category,L4F_WARN, &
2138! ">1 variables refer to v wind component, destaggering will not be done ")
2139! DEALLOCATE(varbufr)
2140! RETURN
2141!endif
2142!
2143!if (nvaru == 0 .and. nvarv == 0) then
2144! call l4f_category_log(this%category,L4F_WARN, &
2145! "no u or v wind component found in volume, nothing to do")
2146! DEALLOCATE(varbufr)
2147! RETURN
2148!endif
2149!
2150!if (COUNT(varbufr/=varu .and. varbufr/=varv) > 0) then
2151! call l4f_category_log(this%category,L4F_WARN, &
2152! "there are variables different from u and v wind component in C grid")
2153!endif
2154
2155
Apply the conversion function this to values. Definition volgrid6d_var_class.F90:390 Apply the conversion function this to values. Definition volgrid6d_var_class.F90:396 Destructor for the corresponding object, it assigns it to a missing value. Definition volgrid6d_var_class.F90:304 Display on the screen a brief content of object. Definition volgrid6d_var_class.F90:376 Initialize a volgrid6d_var object with the optional arguments provided. Definition volgrid6d_var_class.F90:298 This module defines an abstract interface to different drivers for access to files containing gridded... Definition grid_id_class.F90:249 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. Definition missing_values.f90:50 Classe per la gestione delle variabili osservate da stazioni meteo e affini. Definition vol7d_var_class.F90:212 Class for managing physical variables in a grib 1/2 fashion. Definition volgrid6d_var_class.F90:218 Definisce una variabile meteorologica osservata o un suo attributo. Definition vol7d_var_class.F90:226 Class defining a real conversion function between units. Definition volgrid6d_var_class.F90:265 Definition of a physical variable in grib coding style. Definition volgrid6d_var_class.F90:232 |