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