libsim Versione 8.0.0

◆ display_volgrid6d_var()

subroutine display_volgrid6d_var ( type(volgrid6d_var), intent(in) this)
private

Display on the screen a brief content of volgrid6d_var object.

Parametri
[in]thisvolgrid6d_var object to display

Definizione alla linea 1072 del file volgrid6d_var_class.F90.

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