|
libsim Versione 8.0.0
|
◆ volgrid6d_compute_vert_coord_var()
Method for building a volume containing the vertical coordinate as a variable. This method produces a volgrid6d volume, derived from this, containing a single variable, horizontally constant, on the same input levels, which describes the vertical coordinate in the form of a physical variable. The grid, time and timerange metadata are the same as for the original volume. Only a single vertical level type, the one matching the level argument, is converted to a variable. The level argument can also indicate the layer between two surfaces of the same type, in that case the variable representing the vertical coordinate will be set to the value of the midpoint between the two layers. If something goes wrong, e.g. no level matches level argument or the level canot be converted to a physical value, an empty volume is returned.
Definizione alla linea 1041 del file volgrid6d_class_compute.F90. 1042! Copyright (C) 2010 ARPA-SIM <urpsim@smr.arpa.emr.it>
1043! authors:
1044! Davide Cesari <dcesari@arpa.emr.it>
1045! Paolo Patruno <ppatruno@arpa.emr.it>
1046
1047! This program is free software; you can redistribute it and/or
1048! modify it under the terms of the GNU General Public License as
1049! published by the Free Software Foundation; either version 2 of
1050! the License, or (at your option) any later version.
1051
1052! This program is distributed in the hope that it will be useful,
1053! but WITHOUT ANY WARRANTY; without even the implied warranty of
1054! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1055! GNU General Public License for more details.
1056
1057! You should have received a copy of the GNU General Public License
1058! along with this program. If not, see <http://www.gnu.org/licenses/>.
1059#include "config.h"
1060!> Extension of volgrid6d_class with methods for performing simple
1061!! statistical operations on entire volumes of data. This module
1062!! includes methods for performing operations such as (re)averaging
1063!! and (re)cumulation in time of entire volgrid6d_class::volgrid6d
1064!! objects.
1065!!
1066!! \ingroup volgrid6d
1074IMPLICIT NONE
1075
1076CONTAINS
1077
1078!> General-purpose method for computing a statistical processing on
1079!! data in a volgrid6d object already processed with the same statistical
1080!! processing, on a different time interval specified by \a step and
1081!! \a start. This method tries to apply all the suitable specialized
1082!! statistical processing methods according to the input and output
1083!! statistical processing requested. The argument \a stat_proc_input
1084!! determines which data will be processed, while the \a stat_proc
1085!! argument determines the type of statistical process to be applied
1086!! and which will be owned by output data.
1087!!
1088!! The possible combinations are:
1089!!
1090!! - \a stat_proc_input = 254
1091!! - \a stat_proc = 0 average instantaneous observations
1092!! - \a stat_proc = 2 compute maximum of instantaneous observations
1093!! - \a stat_proc = 3 compute minimum of instantaneous observations
1094!! - \a stat_proc = 4 compute difference of instantaneous observations
1095!!
1096!! processing is computed on longer time intervals by aggregation,
1097!! see the description of volgrid6d_compute_stat_proc_agg()
1098!!
1099!! - \a stat_proc_input = *
1100!! - \a stat_proc = 254 consider statistically processed values as
1101!! instantaneous without any extra processing
1102!!
1103!! see the description of volgrid6d_decompute_stat_proc()
1104!!
1105!! - \a stat_proc_input = 0, 1, 2, 3, 4, 200
1106!! - \a stat_proc = \a stat_proc_input recompute input data on
1107!! different intervals
1108!!
1109!! the same statistical processing is applied to obtain data
1110!! processed on a different interval, either longer, by
1111!! aggregation, or shorter, by differences, see the description of
1112!! volgrid6d_recompute_stat_proc_agg() and
1113!! volgrid6d_recompute_stat_proc_diff() respectively; it is also
1114!! possible to provide \a stat_proc_input \a /= \a stat_proc, but
1115!! it has to be used with care.
1116!!
1117!! - \a stat_proc_input = 0
1118!! - \a stat_proc = 1
1119!!
1120!! a time-averaged rate or flux is transformed into a
1121!! time-integrated value (sometimes called accumulated) on the same
1122!! interval by multiplying the values by the length of the time
1123!! interval in seconds, keeping constant all the rest, including
1124!! the variable; the unit of the variable implicitly changes
1125!! accordingly, this is supported officially in grib2 standard, in
1126!! the other cases it is a forcing of the standards.
1127!!
1128!! - \a stat_proc_input = 1
1129!! - \a stat_proc = 0
1130!!
1131!! a time-integrated value (sometimes called accumulated) is
1132!! transformed into a time-averaged rate or flux on the same
1133!! interval by dividing the values by the length of the time
1134!! interval in seconds, see also the previous description of the
1135!! opposite computation.
1136!!
1137!! If a particular statistical processing cannot be performed on the
1138!! input data, the program continues with a warning and, if requested,
1139!! the input data is passed over to the volume specified by the \a
1140!! other argument, in order to allow continuation of processing. All
1141!! the other parameters are passed over to the specifical statistical
1142!! processing methods and are documented there.
1143SUBROUTINE volgrid6d_compute_stat_proc(this, that, stat_proc_input, stat_proc, &
1144 step, start, full_steps, frac_valid, max_step, weighted, clone)
1145TYPE(volgrid6d),INTENT(inout) :: this !< volume providing data to be recomputed, it is not modified by the method, apart from performing a \a volgrid6d_alloc_vol on it
1146TYPE(volgrid6d),INTENT(out) :: that !< output volume which will contain the recomputed data
1147INTEGER,INTENT(in) :: stat_proc_input !< type of statistical processing of data that has to be processed (from grib2 table), only data having timerange of this type will be processed, the actual statistical processing performed and which will appear in the output volume, is however determined by \a stat_proc argument
1148INTEGER,INTENT(in) :: stat_proc !< type of statistical processing to be recomputed (from grib2 table), data in output volume \a that will have a timerange of this type
1149TYPE(timedelta),INTENT(in) :: step !< length of the step over which the statistical processing is performed
1150TYPE(datetime),INTENT(in),OPTIONAL :: start !< start of statistical processing interval
1151LOGICAL,INTENT(in),OPTIONAL :: full_steps !< if \a .TRUE. apply processing only on intervals starting at a forecast time or a reference time modulo \a step
1152REAL,INTENT(in),OPTIONAL :: frac_valid !< minimum fraction of valid data required for considering acceptable a recomputed value, default=1.
1153TYPE(timedelta),INTENT(in),OPTIONAL :: max_step ! maximum allowed distance in time between two single valid data within a dataset, for the dataset to be eligible for statistical processing
1154LOGICAL,INTENT(in),OPTIONAL :: weighted !< if provided and \c .TRUE., the statistical process is computed, if possible, by weighting every value with a weight proportional to its validity interval
1155LOGICAL , INTENT(in),OPTIONAL :: clone !< if provided and \c .TRUE. , clone the gaid's from \a this to \a that
1156
1157INTEGER :: dtmax, dtstep
1158
1159
1160IF (stat_proc_input == 254) THEN
1161 CALL l4f_category_log(this%category, l4f_info, &
1162 'computing statistical processing by aggregation '//&
1164
1165 CALL volgrid6d_compute_stat_proc_agg(this, that, stat_proc, &
1166 step, start, full_steps, max_step, clone)
1167
1168ELSE IF (stat_proc == 254) THEN
1169 CALL l4f_category_log(this%category, l4f_error, &
1170 'statistical processing to instantaneous data not implemented for gridded fields')
1171 CALL raise_error()
1172
1173ELSE IF (stat_proc_input == stat_proc .OR. &
1174 (stat_proc == 0 .OR. stat_proc == 2 .OR. stat_proc == 3)) THEN
1175! avg, min and max can be computed from any input, with care
1176
1177 IF (count(this%timerange(:)%timerange == stat_proc_input) == 0) THEN
1178 CALL l4f_category_log(this%category, l4f_warn, &
1180! return an empty volume, without signaling error
1182 CALL volgrid6d_alloc_vol(that)
1183
1184 ELSE
1185! euristically determine whether aggregation or difference is more suitable
1186 dtmax = maxval(this%timerange(:)%p2, &
1187 mask=(this%timerange(:)%timerange == stat_proc))
1189
1190#ifdef DEBUG
1191 CALL l4f_category_log(this%category, l4f_debug, &
1193#endif
1194
1195 IF (dtstep <= dtmax) THEN
1196 CALL l4f_category_log(this%category, l4f_info, &
1197 'recomputing statistically processed data by difference '// &
1199 CALL volgrid6d_recompute_stat_proc_diff(this, that, stat_proc, step, &
1200 full_steps, start, clone)
1201 ELSE
1202 CALL l4f_category_log(this%category, l4f_info, &
1203 'recomputing statistically processed data by aggregation '// &
1205 CALL volgrid6d_recompute_stat_proc_agg(this, that, stat_proc, step, start, &
1206 full_steps, frac_valid, clone, stat_proc_input)
1207 ENDIF
1208 ENDIF
1209
1210ELSE ! IF (stat_proc_input /= stat_proc) THEN
1211 IF ((stat_proc_input == 0 .AND. stat_proc == 1) .OR. &
1212 (stat_proc_input == 1 .AND. stat_proc == 0)) THEN
1213 CALL l4f_category_log(this%category, l4f_info, &
1214 'computing statistically processed data by integration/differentiation '// &
1216 CALL volgrid6d_compute_stat_proc_metamorph(this, that, stat_proc_input, &
1217 stat_proc, clone)
1218 ELSE
1219 CALL l4f_category_log(this%category, l4f_error, &
1221 ' not implemented or does not make sense')
1222 CALL raise_error()
1223 ENDIF
1224
1225ENDIF
1226
1227END SUBROUTINE volgrid6d_compute_stat_proc
1228
1229
1230!> Specialized method for statistically processing a set of data
1231!! already processed with the same statistical processing, on a
1232!! different time interval. This method performs statistical
1233!! processing by aggregation of shorter intervals.
1234!!
1235!! The output \a that volgrid6d object contains elements from the original volume
1236!! \a this satisfying the conditions
1237!! - timerange (vol7d_timerange_class::vol7d_timerange::timerange)
1238!! of type \a stat_proc (or \a stat_proc_input if provided)
1239!! - any p1 (analysis/observation or forecast)
1240!! - p2 > 0 (processing interval non null, non instantaneous data)
1241!! and equal to a multiplier of \a step
1242!!
1243!! Output data will have timerange of type \a stat_proc and p2 = \a
1244!! step. The supported statistical processing methods (parameter \a
1245!! stat_proc) are:
1246!!
1247!! - 0 average
1248!! - 1 accumulation
1249!! - 2 maximum
1250!! - 3 minimum
1251!! - 4 difference
1252!! - 200 vectorial mean
1253!!
1254!! The start of processing period can be computed automatically from
1255!! the input intervals as the first possible interval modulo \a step,
1256!! or, for a better control, it can be specified explicitely by the
1257!! optional argument \a start. Be warned that, in the final volume,
1258!! the first reference time will actually be \a start \a + \a step,
1259!! since \a start indicates the beginning of first processing
1260!! interval, while reference time (for analysis/oservation) is the end
1261!! of the interval.
1262!!
1263!! The purpose of the optional argument \a stat_proc_input is to allow
1264!! processing with a certain statistical processing operator a dataset
1265!! already processed with a different operator, by specifying the
1266!! latter as stat_proc_input; this is useful, for example, if one
1267!! wants to compute the monthly average of daily maximum temperatures;
1268!! however this has to be used with care since the resulting data
1269!! volume will not carry all the information about the processing
1270!! which has been done, in the previous case, for example, the
1271!! temperatures will simply look like monthly average temperatures.
1272SUBROUTINE volgrid6d_recompute_stat_proc_agg(this, that, stat_proc, &
1273 step, start, full_steps, frac_valid, clone, stat_proc_input)
1274TYPE(volgrid6d),INTENT(inout) :: this !< volume providing data to be recomputed, it is not modified by the method, apart from performing a \a volgrid6d_alloc_vol on it
1275TYPE(volgrid6d),INTENT(out) :: that !< output volume which will contain the recomputed data
1276INTEGER,INTENT(in) :: stat_proc !< type of statistical processing to be recomputed (from grib2 table), only data having timerange of this type will be recomputed and will appear in the output volume
1277TYPE(timedelta),INTENT(in) :: step !< length of the step over which the statistical processing is performed
1278TYPE(datetime),INTENT(in),OPTIONAL :: start !< start of statistical processing interval
1279LOGICAL,INTENT(in),OPTIONAL :: full_steps !< if \a .TRUE. and \a start is not provided, apply processing only on intervals starting at a forecast time or a reference time modulo \a step
1280REAL,INTENT(in),OPTIONAL :: frac_valid !< minimum fraction of valid data required for considering acceptable a recomputed value, default=1.
1281LOGICAL, INTENT(in),OPTIONAL :: clone !< if provided and \c .TRUE. , clone the gaid's from \a this to \a that
1282INTEGER,INTENT(in),OPTIONAL :: stat_proc_input !< to be used with care, type of statistical processing of data that has to be processed (from grib2 table), only data having timerange of this type will be recomputed, the actual statistical processing performed and which will appear in the output volume, is however determined by \a stat_proc argument
1283
1284INTEGER :: tri
1285INTEGER i, j, n, n1, ndtr, i3, i6
1286TYPE(arrayof_ttr_mapper),POINTER :: map_ttr(:,:)
1287INTEGER,POINTER :: dtratio(:)
1288REAL :: lfrac_valid
1289LOGICAL :: lclone
1290REAL,POINTER :: voldatiin(:,:), voldatiout(:,:)
1291
1292
1293NULLIFY(voldatiin, voldatiout)
1294IF (PRESENT(stat_proc_input)) THEN
1295 tri = stat_proc_input
1296ELSE
1297 tri = stat_proc
1298ENDIF
1299IF (PRESENT(frac_valid)) THEN
1300 lfrac_valid = frac_valid
1301ELSE
1302 lfrac_valid = 1.0
1303ENDIF
1304
1306! be safe
1307CALL volgrid6d_alloc_vol(this)
1308
1309! when volume is not decoded it is better to clone anyway to avoid
1310! overwriting fields
1311lclone = optio_log(clone) .OR. .NOT.ASSOCIATED(this%voldati)
1312! initialise the output volume
1314CALL volgrid6d_alloc(that, dim=this%griddim%dim, ntimerange=1, &
1315 nlevel=SIZE(this%level), nvar=SIZE(this%var), ini=.false.)
1316that%level = this%level
1317that%var = this%var
1318
1319CALL recompute_stat_proc_agg_common(this%time, this%timerange, stat_proc, tri, &
1320 step, this%time_definition, that%time, that%timerange, map_ttr, &
1321 dtratio=dtratio, start=start, full_steps=full_steps)
1322
1323CALL volgrid6d_alloc_vol(that, decode=ASSOCIATED(this%voldati))
1324
1325do_otimerange: DO j = 1, SIZE(that%timerange)
1326 do_otime: DO i = 1, SIZE(that%time)
1327
1328 DO n1 = 1, SIZE(dtratio)
1329 IF (dtratio(n1) <= 0) cycle ! safety check
1330
1331 DO i6 = 1, SIZE(this%var)
1332 DO i3 = 1, SIZE(this%level)
1333 CALL volgrid_get_vol_2d(that, i3, i, j, i6, voldatiout)
1334 ndtr = 0
1335 DO n = 1, map_ttr(i,j)%arraysize
1336 IF (map_ttr(i,j)%array(n)%extra_info == dtratio(n1)) THEN
1337 ndtr = ndtr + 1
1338 CALL volgrid_get_vol_2d(this, i3, map_ttr(i,j)%array(n)%it, &
1339 map_ttr(i,j)%array(n)%itr, i6, voldatiin)
1340
1341 IF (ndtr == 1) THEN
1342 voldatiout = voldatiin
1343 IF (lclone) THEN
1345 map_ttr(i,j)%array(n)%itr,i6), that%gaid(i3,i,j,i6))
1346 ELSE
1347 that%gaid(i3,i,j,i6) = this%gaid(i3, map_ttr(i,j)%array(n)%it, &
1348 map_ttr(i,j)%array(n)%itr,i6)
1349 ENDIF
1350
1351 ELSE ! second or more time
1352 SELECT CASE(stat_proc)
1353 CASE (0, 200, 1, 4) ! average, vectorial mean, accumulation, difference
1355 voldatiout(:,:) = voldatiout(:,:) + voldatiin(:,:)
1356 ELSEWHERE
1357 voldatiout(:,:) = rmiss
1358 END WHERE
1359 CASE(2) ! maximum
1361 voldatiout(:,:) = max(voldatiout(:,:), voldatiin(:,:))
1362 ELSEWHERE
1363 voldatiout(:,:) = rmiss
1364 END WHERE
1365 CASE(3) ! minimum
1367 voldatiout(:,:) = min(voldatiout(:,:), voldatiin(:,:))
1368 ELSEWHERE
1369 voldatiout(:,:) = rmiss
1370 END WHERE
1371 END SELECT
1372
1373 ENDIF ! first time
1374 ENDIF ! dtratio(n1)
1375 ENDDO ! ttr
1376
1377#ifdef DEBUG
1378 CALL l4f_log(l4f_debug, &
1379 'compute_stat_proc_agg, ndtr/dtratio/frac_valid: '// &
1381#endif
1382 IF (ndtr > 0) THEN ! why this condition was not here before?
1383 IF (real(ndtr)/real(dtratio(n1)) >= lfrac_valid) THEN ! success
1384 IF (stat_proc == 0) THEN ! average
1386 voldatiout(:,:) = voldatiout(:,:)/ndtr
1387 END WHERE
1388 ENDIF
1389 CALL volgrid_set_vol_2d(that, i3, i, j, i6, voldatiout)
1390#ifdef DEBUG
1391 CALL l4f_log(l4f_debug, &
1392 'compute_stat_proc_agg, coding lev/t/tr/var: '// &
1394#endif
1395 ELSE
1396! must nullify the output gaid here, otherwise an incomplete field will be output
1397 IF (lclone) THEN
1399 ELSE
1401 ENDIF
1402#ifdef DEBUG
1403 CALL l4f_log(l4f_debug, &
1404 'compute_stat_proc_agg, skipping lev/t/tr/var: '// &
1406#endif
1407 ENDIF
1408 ENDIF ! ndtr > 0
1409
1410 ENDDO ! level
1411 ENDDO ! var
1412 ENDDO ! dtratio
1414 ENDDO do_otime
1415ENDDO do_otimerange
1416
1417DEALLOCATE(dtratio, map_ttr)
1418
1419END SUBROUTINE volgrid6d_recompute_stat_proc_agg
1420
1421
1422!> Method for statistically processing a set of instantaneous data.
1423!! This method performs statistical processing by aggregation of
1424!! instantaneous data.
1425!!
1426!! The output \a that volgrid6d object contains elements from the original volume
1427!! \a this satisfying the conditions
1428!! - timerange (vol7d_timerange_class::vol7d_timerange::timerange)
1429!! of type 254 (instantaeous)
1430!! - any p1 (analysis/observation or forecast)
1431!! - p2 = 0 (processing interval null, instantaneous data)
1432!!
1433!! Output data will have timerange of type \a stat_proc, and p2 = \a
1434!! step. The supported statistical processing methods (parameter \a
1435!! stat_proc) are:
1436!!
1437!! - 0 average
1438!! - 2 maximum
1439!! - 3 minimum
1440!! - 4 difference
1441!!
1442!! A maximum distance in time for input valid data can be assigned
1443!! with the optional argument \a max_step, in order to filter datasets
1444!! with too long "holes".
1445SUBROUTINE volgrid6d_compute_stat_proc_agg(this, that, stat_proc, &
1446 step, start, full_steps, max_step, clone)
1447TYPE(volgrid6d),INTENT(inout) :: this !< volume providing data to be recomputed, it is not modified by the method, apart from performing a \a volgrid6d_alloc_vol on it
1448TYPE(volgrid6d),INTENT(out) :: that !< output volume which will contain the recomputed data
1449INTEGER,INTENT(in) :: stat_proc !< type of statistical processing to be recomputed (from grib2 table), only data having timerange of this type will be recomputed and will appear in the output volume
1450TYPE(timedelta),INTENT(in) :: step !< length of the step over which the statistical processing is performed
1451TYPE(datetime),INTENT(in),OPTIONAL :: start !< start of statistical processing interval
1452LOGICAL,INTENT(in),OPTIONAL :: full_steps !< if \a .TRUE. and \a start is not provided, apply processing only on intervals starting at a forecast time or a reference time modulo \a step
1453TYPE(timedelta),INTENT(in),OPTIONAL :: max_step !< maximum allowed distance in time between two contiguougs valid data within an interval, for the interval to be eligible for statistical processing
1454LOGICAL , INTENT(in),OPTIONAL :: clone !< if provided and \c .TRUE. , clone the gaid's from \a this to \a that
1455
1456INTEGER :: tri
1457INTEGER i, j, n, ninp, i3, i6
1458TYPE(arrayof_ttr_mapper),POINTER :: map_ttr(:,:)
1459TYPE(timedelta) :: lmax_step
1460LOGICAL :: lclone
1461REAL,POINTER :: voldatiin(:,:), voldatiout(:,:)
1462
1463
1464NULLIFY(voldatiin, voldatiout)
1465tri = 254
1466IF (PRESENT(max_step)) THEN
1467 lmax_step = max_step
1468ELSE
1469 lmax_step = timedelta_max
1470ENDIF
1471
1473! be safe
1474CALL volgrid6d_alloc_vol(this)
1475
1476! when volume is not decoded it is better to clone anyway to avoid
1477! overwriting fields
1478lclone = optio_log(clone) .OR. .NOT.ASSOCIATED(this%voldati)
1479! initialise the output volume
1481CALL volgrid6d_alloc(that, dim=this%griddim%dim, ntimerange=1, &
1482 nlevel=SIZE(this%level), nvar=SIZE(this%var), ini=.false.)
1483that%level = this%level
1484that%var = this%var
1485
1486CALL recompute_stat_proc_agg_common(this%time, this%timerange, stat_proc, tri, &
1487 step, this%time_definition, that%time, that%timerange, map_ttr, &
1488 start=start, full_steps=full_steps)
1489
1490CALL volgrid6d_alloc_vol(that, decode=ASSOCIATED(this%voldati))
1491
1492do_otimerange: DO j = 1, SIZE(that%timerange)
1493 do_otime: DO i = 1, SIZE(that%time)
1494 ninp = map_ttr(i,j)%arraysize
1495 IF (ninp <= 0) cycle do_otime
1496
1497 IF (stat_proc == 4) THEN ! check validity for difference
1498 IF (map_ttr(i,j)%array(1)%extra_info /= 1 .OR. &
1499 map_ttr(i,j)%array(ninp)%extra_info /= 2) THEN
1501 cycle do_otime
1502 ENDIF
1503 ELSE
1504! check validity condition (missing values in volume are not accounted for)
1505 DO n = 2, ninp
1506 IF (map_ttr(i,j)%array(n)%time - map_ttr(i,j)%array(n-1)%time > &
1507 lmax_step) THEN
1509 cycle do_otime
1510 ENDIF
1511 ENDDO
1512 ENDIF
1513
1514 DO i6 = 1, SIZE(this%var)
1515 DO i3 = 1, SIZE(this%level)
1516 CALL volgrid_get_vol_2d(that, i3, i, j, i6, voldatiout)
1517
1518 IF (stat_proc == 4) THEN ! special treatment for difference
1519 IF (lclone) THEN
1521 map_ttr(i,j)%array(1)%itr,i6), that%gaid(i3,i,j,i6))
1522 ELSE
1523 that%gaid(i3,i,j,i6) = this%gaid(i3, map_ttr(i,j)%array(1)%it, &
1524 map_ttr(i,j)%array(1)%itr,i6)
1525 ENDIF
1526! improve the next workflow?
1527 CALL volgrid_get_vol_2d(this, i3, map_ttr(i,j)%array(ninp)%it, &
1528 map_ttr(i,j)%array(ninp)%itr, i6, voldatiin)
1529 voldatiout = voldatiin
1530 CALL volgrid_get_vol_2d(this, i3, map_ttr(i,j)%array(1)%it, &
1531 map_ttr(i,j)%array(1)%itr, i6, voldatiin)
1532
1534 voldatiout(:,:) = voldatiout(:,:) - voldatiin(:,:)
1535 ELSEWHERE
1536 voldatiout(:,:) = rmiss
1537 END WHERE
1538
1539 ELSE ! other stat_proc
1540 DO n = 1, ninp
1541 CALL volgrid_get_vol_2d(this, i3, map_ttr(i,j)%array(n)%it, &
1542 map_ttr(i,j)%array(n)%itr, i6, voldatiin)
1543
1544 IF (n == 1) THEN
1545 voldatiout = voldatiin
1546 IF (lclone) THEN
1548 map_ttr(i,j)%array(n)%itr,i6), that%gaid(i3,i,j,i6))
1549 ELSE
1550 that%gaid(i3,i,j,i6) = this%gaid(i3, map_ttr(i,j)%array(n)%it, &
1551 map_ttr(i,j)%array(n)%itr,i6)
1552 ENDIF
1553
1554 ELSE ! second or more time
1555 SELECT CASE(stat_proc)
1556 CASE (0, 1) ! average, accumulation
1558 voldatiout(:,:) = voldatiout(:,:) + voldatiin(:,:)
1559 ELSEWHERE
1560 voldatiout(:,:) = rmiss
1561 END WHERE
1562 CASE(2) ! maximum
1564 voldatiout(:,:) = max(voldatiout(:,:), voldatiin(:,:))
1565 ELSEWHERE
1566 voldatiout(:,:) = rmiss
1567 END WHERE
1568 CASE(3) ! minimum
1570 voldatiout(:,:) = min(voldatiout(:,:), voldatiin(:,:))
1571 ELSEWHERE
1572 voldatiout(:,:) = rmiss
1573 END WHERE
1574 END SELECT
1575
1576 ENDIF ! first time
1577 ENDDO
1578 IF (stat_proc == 0) THEN ! average
1580 voldatiout(:,:) = voldatiout(:,:)/ninp
1581 END WHERE
1582 ENDIF
1583 ENDIF
1584 CALL volgrid_set_vol_2d(that, i3, i, j, i6, voldatiout)
1585 ENDDO ! level
1586 ENDDO ! var
1588 ENDDO do_otime
1589ENDDO do_otimerange
1590
1591DEALLOCATE(map_ttr)
1592
1593
1594END SUBROUTINE volgrid6d_compute_stat_proc_agg
1595
1596
1597!> Specialized method for statistically processing a set of data
1598!! already processed with the same statistical processing, on a
1599!! different time interval. This method performs statistical
1600!! processing by difference of different intervals. Data with both
1601!! analysis/observation or forecast timerange are processed.
1602!!
1603!! The output \a that volgrid6d object contains elements from the original volume
1604!! \a this satisfying the conditions
1605!! - timerange (vol7d_timerange_class::vol7d_timerange::timerange)
1606!! of type \a stat_proc
1607!! - any p1 (analysis/observation or forecast)
1608!! - p2 > 0 (processing interval non null, non instantaneous data)
1609!! and equal to a multiplier of \a step if \a full_steps is \c .TRUE.
1610!!
1611!! Output data will have timerange of type \a stat_proc and p2 = \a
1612!! step. The supported statistical processing methods (parameter \a
1613!! stat_proc) are:
1614!!
1615!! - 0 average
1616!! - 1 accumulation
1617!! - 4 difference
1618!!
1619!! Input volume may have any value of \a this%time_definition, and
1620!! that value will be conserved in the output volume.
1621SUBROUTINE volgrid6d_recompute_stat_proc_diff(this, that, stat_proc, step, full_steps, start, clone)
1622TYPE(volgrid6d),INTENT(inout) :: this !< volume providing data to be recomputed, it is not modified by the method, apart from performing a \a volgrid6d_alloc_vol on it
1623TYPE(volgrid6d),INTENT(out) :: that !< output volume which will contain the recomputed data
1624INTEGER,INTENT(in) :: stat_proc !< type of statistical processing to be recomputed (from grib2 table), only data having timerange of this type will be recomputed and will appear in the output volume
1625TYPE(timedelta),INTENT(in) :: step !< length of the step over which the statistical processing is performed
1626LOGICAL,INTENT(in),OPTIONAL :: full_steps !< if provided and \a .TRUE., process only data having processing interval (p2) equal to a multiple of \a step
1627TYPE(datetime),INTENT(in),OPTIONAL :: start !< if provided, together with \a full_steps, processes data on intervals starting at \a start +- an integer amount of \a step intervals
1628LOGICAL,INTENT(in),OPTIONAL :: clone !< if provided and \c .TRUE. , clone the gaid's from \a this to \a that
1629INTEGER :: i3, i4, i6, i, j, k, l, nitr, steps
1630INTEGER,ALLOCATABLE :: map_tr(:,:,:,:,:), f(:), keep_tr(:,:,:)
1631REAL,POINTER :: voldatiin1(:,:), voldatiin2(:,:), voldatiout(:,:)
1632!LOGICAL,POINTER :: mask_timerange(:)
1633LOGICAL :: lclone
1634TYPE(vol7d_var),ALLOCATABLE :: varbufr(:)
1635
1636
1637! be safe
1638CALL volgrid6d_alloc_vol(this)
1639! when volume is not decoded it is better to clone anyway to avoid
1640! overwriting fields
1641lclone = optio_log(clone) .OR. .NOT.ASSOCIATED(this%voldati)
1642! initialise the output volume
1644CALL volgrid6d_alloc(that, dim=this%griddim%dim, &
1645 nlevel=SIZE(this%level), nvar=SIZE(this%var), ini=.false.)
1646that%level = this%level
1647that%var = this%var
1648
1649! compute length of cumulation step in seconds
1651
1652! compute the statistical processing relations, output time and
1653! timerange are defined here
1654CALL recompute_stat_proc_diff_common(this%time, this%timerange, stat_proc, step, &
1655 that%time, that%timerange, map_tr, f, keep_tr, &
1656 this%time_definition, full_steps, start)
1657nitr = SIZE(f)
1658
1659! complete the definition of the output volume
1660CALL volgrid6d_alloc_vol(that, decode=ASSOCIATED(this%voldati))
1661! allocate workspace once
1662IF (.NOT.ASSOCIATED(that%voldati)) THEN
1663 ALLOCATE(voldatiin1(this%griddim%dim%nx, this%griddim%dim%ny), &
1664 voldatiin2(this%griddim%dim%nx, this%griddim%dim%ny), &
1665 voldatiout(this%griddim%dim%nx, this%griddim%dim%ny))
1666ENDIF
1667
1668! copy the timeranges already satisfying the requested step, if any
1669DO i4 = 1, SIZE(this%time)
1670 DO i = 1, nitr
1672 l = keep_tr(i, i4, 1)
1673 k = keep_tr(i, i4, 2)
1674#ifdef DEBUG
1675 CALL l4f_category_log(this%category, l4f_debug, &
1678#endif
1679 DO i6 = 1, SIZE(this%var)
1680 DO i3 = 1, SIZE(this%level)
1682 IF (lclone) THEN
1684 ELSE
1685 that%gaid(i3,l,k,i6) = this%gaid(i3,i4,f(i),i6)
1686 ENDIF
1687 IF (ASSOCIATED(that%voldati)) THEN
1688 that%voldati(:,:,i3,l,k,i6) = this%voldati(:,:,i3,i4,f(i),i6)
1689 ELSE
1690 CALL volgrid_get_vol_2d(this, i3, i4, f(i), i6, voldatiout)
1691 CALL volgrid_set_vol_2d(that, i3, l, k, i6, voldatiout)
1692 ENDIF
1693 ENDIF
1694 ENDDO
1695 ENDDO
1696 ENDIF
1697 ENDDO
1698ENDDO
1699
1700! varbufr required for setting posdef, optimize with an array
1701IF (stat_proc == 1) THEN
1702 ALLOCATE(varbufr(SIZE(this%var)))
1703 DO i6 = 1, SIZE(this%var)
1704 varbufr(i6) = convert(this%var(i6))
1705 CALL vol7d_var_features_set(varbufr(i6))
1706 ENDDO
1707ENDIF
1708! compute statistical processing
1709DO l = 1, SIZE(this%time)
1710 DO k = 1, nitr
1711 DO j = 1, SIZE(this%time)
1712 DO i = 1, nitr
1714 DO i6 = 1, SIZE(this%var)
1715 DO i3 = 1, SIZE(this%level)
1716
1719! take the gaid from the second time/timerange contributing to the
1720! result (l,f(k))
1721 IF (lclone) THEN
1723 that%gaid(i3,map_tr(i,j,k,l,1),map_tr(i,j,k,l,2),i6))
1724 ELSE
1725 that%gaid(i3,map_tr(i,j,k,l,1),map_tr(i,j,k,l,2),i6) = &
1726 this%gaid(i3,l,f(k),i6)
1727 ENDIF
1728
1729! get/set 2d sections API is used
1730 CALL volgrid_get_vol_2d(this, i3, l, f(k), i6, voldatiin1)
1731 CALL volgrid_get_vol_2d(this, i3, j, f(i), i6, voldatiin2)
1732 IF (ASSOCIATED(that%voldati)) &
1733 CALL volgrid_get_vol_2d(that, i3, &
1734 map_tr(i,j,k,l,1), map_tr(i,j,k,l,2), i6, voldatiout)
1735
1736 IF (stat_proc == 0) THEN ! average
1738 voldatiout(:,:) = &
1739 (voldatiin1(:,:)*this%timerange(f(k))%p2 - &
1740 voldatiin2(:,:)*this%timerange(f(i))%p2)/ &
1741 steps
1742 ELSEWHERE
1743 voldatiout(:,:) = rmiss
1744 END WHERE
1745 ELSE IF (stat_proc == 1 .OR. stat_proc == 4) THEN ! acc, diff
1747 voldatiout(:,:) = voldatiin1(:,:) - voldatiin2(:,:)
1748 ELSEWHERE
1749 voldatiout(:,:) = rmiss
1750 END WHERE
1751 IF (stat_proc == 1) THEN
1752 CALL vol7d_var_features_posdef_apply(varbufr(i6), voldatiout)
1753 ENDIF
1754 ENDIF
1755
1756 CALL volgrid_set_vol_2d(that, i3, &
1757 map_tr(i,j,k,l,1), map_tr(i,j,k,l,2), i6, voldatiout)
1758
1759 ENDIF
1760 ENDDO
1761 ENDDO
1762 ENDIF
1763 ENDDO
1764 ENDDO
1765 ENDDO
1766ENDDO
1767
1768IF (.NOT.ASSOCIATED(that%voldati)) THEN
1769 DEALLOCATE(voldatiin1, voldatiin2, voldatiout)
1770ENDIF
1771
1772END SUBROUTINE volgrid6d_recompute_stat_proc_diff
1773
1774
1775!> Specialized method for statistically processing a set of data
1776!! by integration/differentiation.
1777!! This method performs statistical processing by integrating
1778!! (accumulating) in time values representing time-average rates or
1779!! fluxes, (\a stat_proc_input=0 \a stat_proc=1) or by transforming a
1780!! time-integrated (accumulated) value in a time-average rate or flux
1781!! (\a stat_proc_input=1 \a stat_proc=0). Analysis/observation or
1782!! forecast timeranges are processed. The only operation performed is
1783!! respectively multiplying or dividing the values by the length of
1784!! the time interval in seconds.
1785!!
1786!! The output \a that volgrid6d object contains elements from the
1787!! original volume \a this satisfying the conditions
1788!! - timerange (vol7d_timerange_class::vol7d_timerange::timerange)
1789!! of type \a stat_proc_input (0 or 1)
1790!! - any p1 (analysis/observation or forecast)
1791!! - p2 > 0 (processing interval non null, non instantaneous data)
1792!!
1793!! Output data will have timerange of type \a stat_proc (1 or 0) and
1794!! p1 and p2 equal to the corresponding input values. The supported
1795!! statistical processing methods (parameter \a stat_proc) are:
1796!!
1797!! - 0 average
1798!! - 1 accumulation
1799!!
1800!! Input volume may have any value of \a this%time_definition, and
1801!! that value will be conserved in the output volume.
1802SUBROUTINE volgrid6d_compute_stat_proc_metamorph(this, that, stat_proc_input, stat_proc, clone)
1803TYPE(volgrid6d),INTENT(inout) :: this !< volume providing data to be recomputed, it is not modified by the method, apart from performing a \a volgrid6d_alloc_vol on it
1804TYPE(volgrid6d),INTENT(out) :: that !< output volume which will contain the recomputed data
1805INTEGER,INTENT(in) :: stat_proc_input !< type of statistical processing of data that has to be processed (from grib2 table), only data having timerange of this type will be processed, the actual statistical processing performed and which will appear in the output volume, is however determined by \a stat_proc argument
1806INTEGER,INTENT(in) :: stat_proc !< type of statistical processing to be recomputed (from grib2 table), data in output volume \a that will have a timerange of this type
1807LOGICAL , INTENT(in),OPTIONAL :: clone !< if provided and \c .TRUE. , clone the gaid's from \a this to \a that
1808
1809INTEGER :: j, i3, i4, i6
1810INTEGER,POINTER :: map_tr(:)
1811REAL,POINTER :: voldatiin(:,:), voldatiout(:,:)
1812REAL,ALLOCATABLE :: int_ratio(:)
1813LOGICAL :: lclone
1814
1815NULLIFY(voldatiin, voldatiout)
1816
1817! be safe
1818CALL volgrid6d_alloc_vol(this)
1819! when volume is not decoded it is better to clone anyway to avoid
1820! overwriting fields
1821lclone = optio_log(clone) .OR. .NOT.ASSOCIATED(this%voldati)
1822
1823IF (.NOT.((stat_proc_input == 0 .AND. stat_proc == 1) .OR. &
1824 (stat_proc_input == 1 .AND. stat_proc == 0))) THEN
1825
1826 CALL l4f_category_log(this%category, l4f_warn, &
1827 'compute_stat_proc_metamorph, can only be applied to average->accumulated timerange and viceversa')
1828! return an empty volume, without signaling error
1830 CALL volgrid6d_alloc_vol(that)
1831 RETURN
1832ENDIF
1833
1834! initialise the output volume
1836CALL volgrid6d_alloc(that, dim=this%griddim%dim, ntime=SIZE(this%time), &
1837 nlevel=SIZE(this%level), nvar=SIZE(this%var), ini=.false.)
1838that%time = this%time
1839that%level = this%level
1840that%var = this%var
1841
1842CALL compute_stat_proc_metamorph_common(stat_proc_input, this%timerange, stat_proc, &
1843 that%timerange, map_tr)
1844
1845! complete the definition of the output volume
1846CALL volgrid6d_alloc_vol(that, decode=ASSOCIATED(this%voldati))
1847
1848IF (stat_proc == 0) THEN ! average -> integral
1849 int_ratio = 1./real(that%timerange(:)%p2)
1850ELSE ! cumulation
1851 int_ratio = real(that%timerange(:)%p2)
1852ENDIF
1853
1854DO i6 = 1, SIZE(this%var)
1855 DO j = 1, SIZE(map_tr)
1856 DO i4 = 1, SIZE(that%time)
1857 DO i3 = 1, SIZE(this%level)
1858
1859 IF (lclone) THEN
1861 ELSE
1862 that%gaid(i3,i4,map_tr(j),i6) = this%gaid(i3,i4,j,i6)
1863 ENDIF
1864 CALL volgrid_get_vol_2d(this, i3, i4, map_tr(j), i6, voldatiin)
1865 CALL volgrid_get_vol_2d(that, i3, i4, j, i6, voldatiout)
1867 voldatiout = voldatiin*int_ratio(j)
1868 ELSEWHERE
1869 voldatiout = rmiss
1870 END WHERE
1871 CALL volgrid_set_vol_2d(that, i3, i4, j, i6, voldatiout)
1872 ENDDO
1873 ENDDO
1874 ENDDO
1875ENDDO
1876
1877
1878END SUBROUTINE volgrid6d_compute_stat_proc_metamorph
1879
1880!> Method for building a volume containing the vertical coordinate as
1881!! a variable.
1882!! This method produces a volgrid6d volume, derived from \a this,
1883!! containing a single variable, horizontally constant, on the same
1884!! input levels, which describes the vertical coordinate in the form
1885!! of a physical variable. The grid, time and timerange metadata are
1886!! the same as for the original volume. Only a single vertical level
1887!! type, the one matching the \a level argument, is converted to a
1888!! variable. The \a level argument can also indicate the layer between
1889!! two surfaces of the same type, in that case the variable
1890!! representing the vertical coordinate will be set to the value of
1891!! the midpoint between the two layers. If something goes wrong,
1892!! e.g. no level matches \a level argument or the level canot be
1893!! converted to a physical value, an empty volume is returned.
1894SUBROUTINE volgrid6d_compute_vert_coord_var(this, level, volgrid_lev)
1895TYPE(volgrid6d),INTENT(in) :: this !< volume with the vertical levels
1896TYPE(vol7d_level),INTENT(in) :: level !< vertical level to be converted to variable, only the type(s) of level are used not the value(s)
1897TYPE(volgrid6d),INTENT(out) :: volgrid_lev !< output volume with the variable describing the vertical coordinate
1898
1899INTEGER :: nlev, i, ii, iii, iiii
1900TYPE(grid_id) :: out_gaid
1901LOGICAL,ALLOCATABLE :: levmask(:)
1902TYPE(volgrid6d_var) :: lev_var
1903
1905IF (.NOT.ASSOCIATED(this%gaid)) THEN
1906 CALL l4f_log(l4f_error, 'volgrid6d_compute_vert_coord_var: input volume not allocated')
1907 RETURN
1908ENDIF
1909! if layer, both surfaces must be of the same type
1911 CALL l4f_log(l4f_error, 'volgrid6d_compute_vert_coord_var: requested (mixed) layer type not valid')
1912 RETURN
1913ENDIF
1914
1915! look for valid levels to be converted to vars
1916ALLOCATE(levmask(SIZE(this%level)))
1917levmask = this%level%level1 == level%level1 .AND. &
1918 this%level%level2 == level%level2 .AND. c_e(this%level%l1)
1920nlev = count(levmask)
1921IF (nlev == 0) THEN
1922 CALL l4f_log(l4f_error, 'volgrid6d_compute_vert_coord_var: requested level type not available')
1923 RETURN
1924ENDIF
1925
1926out_gaid = grid_id_new()
1927gaidloop: DO i=1 ,SIZE(this%gaid,1)
1928 DO ii=1 ,SIZE(this%gaid,2)
1929 DO iii=1 ,SIZE(this%gaid,3)
1930 DO iiii=1 ,SIZE(this%gaid,4)
1933 EXIT gaidloop
1934 ENDIF
1935 ENDDO
1936 ENDDO
1937 ENDDO
1938ENDDO gaidloop
1939
1940! look for variable corresponding to level
1941lev_var = convert(vol7d_var_new(btable=vol7d_level_to_var(level)), &
1942 grid_id_template=out_gaid)
1944 CALL l4f_log(l4f_error, 'volgrid6d_compute_vert_coord_var: no variable corresponds to requested level type')
1945 RETURN
1946ENDIF
1947
1948! prepare output volume
1950 time_definition=this%time_definition) !, categoryappend=categoryappend)
1951CALL volgrid6d_alloc(volgrid_lev, ntime=SIZE(this%time), nlevel=nlev, &
1952 ntimerange=SIZE(this%timerange), nvar=1)
1953! fill metadata
1954volgrid_lev%time = this%time
1955volgrid_lev%level = pack(this%level, mask=levmask)
1956volgrid_lev%timerange = this%timerange
1957volgrid_lev%var(1) = lev_var
1958
1959CALL volgrid6d_alloc_vol(volgrid_lev, decode=.true.)
1960! fill data
1961DO i = 1, nlev
1963 volgrid_lev%voldati(:,:,i,:,:,:) = real(volgrid_lev%level(i)%l1 + &
1964 volgrid_lev%level(i)%l2)* &
1965 vol7d_level_to_var_factor(volgrid_lev%level(i))/2.
1966 ELSE
1967 volgrid_lev%voldati(:,:,i,:,:,:) = real(volgrid_lev%level(i)%l1)* &
1968 vol7d_level_to_var_factor(volgrid_lev%level(i))
1969 ENDIF
1970ENDDO
1971! fill gaid for subsequent export
1973 DO i=1 ,SIZE(volgrid_lev%gaid,1)
1974 DO ii=1 ,SIZE(volgrid_lev%gaid,2)
1975 DO iii=1 ,SIZE(volgrid_lev%gaid,3)
1976 DO iiii=1 ,SIZE(volgrid_lev%gaid,4)
1978 ENDDO
1979 ENDDO
1980 ENDDO
1981 ENDDO
1983ENDIF
1984
1985END SUBROUTINE volgrid6d_compute_vert_coord_var
1986
Restituiscono il valore dell'oggetto nella forma desiderata. Definition datetime_class.F90:322 Costruttori per le classi datetime e timedelta. Definition datetime_class.F90:311 Functions that return a trimmed CHARACTER representation of the input variable. Definition datetime_class.F90:349 Restituiscono il valore dell'oggetto in forma di stringa stampabile. Definition datetime_class.F90:327 Make a deep copy, if possible, of the grid identifier. Definition grid_id_class.F90:336 Apply the conversion function this to values. Definition volgrid6d_var_class.F90:396 This module defines an abstract interface to different drivers for access to files containing gridded... Definition grid_id_class.F90:249 Module for basic statistical computations taking into account missing data. Definition simple_stat.f90:25 This module contains functions that are only for internal use of the library. Definition stat_proc_engine.F90:211 Extension of volgrid6d_class with methods for performing simple statistical operations on entire volu... Definition volgrid6d_class_compute.F90:214 This module defines objects and methods for managing data volumes on rectangular georeferenced grids. Definition volgrid6d_class.F90:240 Class for managing physical variables in a grib 1/2 fashion. Definition volgrid6d_var_class.F90:218 |