libsim Versione 8.0.0

◆ map_inv_distinct_var6d()

integer function, dimension(dim) map_inv_distinct_var6d ( type(volgrid6d_var), dimension(:), intent(in) vect,
integer, intent(in) dim,
logical, dimension(:), intent(in), optional mask,
logical, intent(in), optional back )
private

map inv distinct

Definizione alla linea 909 del file volgrid6d_var_class.F90.

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