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