libsim Versione 8.0.0

◆ index_var6d()

integer function index_var6d ( type(volgrid6d_var), dimension(:), intent(in) vect,
type(volgrid6d_var), intent(in) search,
logical, dimension(:), intent(in), optional mask,
logical, intent(in), optional back,
integer, intent(in), optional cache )

Cerca l'indice del primo o ultimo elemento di vect uguale a search.

Definizione alla linea 995 del file volgrid6d_var_class.F90.

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