libsim Versione 8.0.0

◆ vargrib2varbufr()

subroutine, public vargrib2varbufr ( type(volgrid6d_var), dimension(:), intent(in) vargrib,
type(vol7d_var), dimension(:), intent(out) varbufr,
type(conv_func), dimension(:), pointer c_func )

Convert a volgrid6d_var array object into a physically equivalent vol7d_var array object.

This method converts a grib-like array of physical variables vargrib, to an array of unique, physically based, bufr-like variables varbufr. 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 vargrib to the corresponding fields in the bufr-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 vol7d_var_miss and the conversion function to conv_func_miss.

Parametri
[in]vargribarray of input grib-like variables
[out]varbufrarray of output bufr-like variables
c_funcpointer to an array of the corresponding conv_func objects, allocated in the method

Definizione alla linea 1092 del file volgrid6d_var_class.F90.

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