libsim Versione 8.0.0

◆ varbufr2vargrib_convert()

type(volgrid6d_var) function varbufr2vargrib_convert ( type(vol7d_var), intent(in) varbufr,
type(conv_func), intent(out), optional c_func,
type(grid_id), intent(in), optional grid_id_template )
private

Convert a vol7d_var object into a physically equivalent volgrid6d_var object.

This method returns a grib-like representation of type volgrid6d_var of the bufr-like input physical variable varbufr. Unlike the opposite convert method, in this case the conversion is not uniqe and at the moment the first matching grib-like variable is chosen, without any control over the choice process. The method optionally returns a conv_func object which can successively be used to convert the numerical values of the field associated to varbufr to the corresponding fields in the grib-like representation. If the conversion is not successful, the output variable is set to volgrid6d_var_miss and the conversion function to conv_func_miss.

Parametri
[in]varbufrinput bufr-like variable
[out]c_funccorresponding conv_func object
[in]grid_id_templatea template (typically grib_api) to which data will be finally exported, it helps in improving variable conversion

Definizione alla linea 1205 del file volgrid6d_var_class.F90.

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