libsim Versione 8.0.0

◆ map_distinct_ttr_mapper()

integer function, dimension(size(vect)) map_distinct_ttr_mapper ( type(ttr_mapper), dimension(:), intent(in) vect,
logical, dimension(:), intent(in), optional mask,
logical, intent(in), optional back )

map distinct

Definizione alla linea 1120 del file stat_proc_engine.F90.

1121! Copyright (C) 2010 ARPA-SIM <urpsim@smr.arpa.emr.it>
1122! authors:
1123! Davide Cesari <dcesari@arpa.emr.it>
1124! Paolo Patruno <ppatruno@arpa.emr.it>
1125
1126! This program is free software; you can redistribute it and/or
1127! modify it under the terms of the GNU General Public License as
1128! published by the Free Software Foundation; either version 2 of
1129! the License, or (at your option) any later version.
1130
1131! This program is distributed in the hope that it will be useful,
1132! but WITHOUT ANY WARRANTY; without even the implied warranty of
1133! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1134! GNU General Public License for more details.
1135
1136! You should have received a copy of the GNU General Public License
1137! along with this program. If not, see <http://www.gnu.org/licenses/>.
1138#include "config.h"
1139!> This module contains functions that are only for internal use of
1140!! the library. It should not be used by user procedures because it is
1141!! subject to change
1142!! \ingroup vol7d
1143MODULE stat_proc_engine
1145USE vol7d_class
1146IMPLICIT NONE
1147
1148! per ogni elemento i,j dell'output, definire n elementi di input ad
1149! esso contribuenti (arrayof_ttr_mapper) con le seguenti informazioni
1150TYPE ttr_mapper
1151 INTEGER :: it=imiss ! k
1152 INTEGER :: itr=imiss ! l
1153 INTEGER :: extra_info=imiss ! dtratio for intervals, extreme for point in time
1154 TYPE(datetime) :: time=datetime_miss ! time for point in time
1155END TYPE ttr_mapper
1156
1157INTERFACE OPERATOR (==)
1158 MODULE PROCEDURE ttr_mapper_eq
1159END INTERFACE
1160
1161INTERFACE OPERATOR (/=)
1162 MODULE PROCEDURE ttr_mapper_ne
1163END INTERFACE
1164
1165INTERFACE OPERATOR (>)
1166 MODULE PROCEDURE ttr_mapper_gt
1167END INTERFACE
1168
1169INTERFACE OPERATOR (<)
1170 MODULE PROCEDURE ttr_mapper_lt
1171END INTERFACE
1172
1173INTERFACE OPERATOR (>=)
1174 MODULE PROCEDURE ttr_mapper_ge
1175END INTERFACE
1176
1177INTERFACE OPERATOR (<=)
1178 MODULE PROCEDURE ttr_mapper_le
1179END INTERFACE
1180
1181#undef VOL7D_POLY_TYPE
1182#undef VOL7D_POLY_TYPES
1183#undef ENABLE_SORT
1184#define VOL7D_POLY_TYPE TYPE(ttr_mapper)
1185#define VOL7D_POLY_TYPES _ttr_mapper
1186#define ENABLE_SORT
1187#include "array_utilities_pre.F90"
1188
1189#define ARRAYOF_ORIGTYPE TYPE(ttr_mapper)
1190#define ARRAYOF_TYPE arrayof_ttr_mapper
1191#define ARRAYOF_ORIGEQ 1
1192#define ARRAYOF_ORIGGT 1
1193#include "arrayof_pre.F90"
1194! from arrayof
1195
1196TYPE,PRIVATE :: ttr_decoder
1197 TYPE(datetime) :: pstart=datetime_miss
1198 TYPE(datetime) :: pend=datetime_miss
1199 TYPE(datetime) :: reftime=datetime_miss
1200 LOGICAL :: isana=.false.
1201END TYPE ttr_decoder
1202
1203CONTAINS
1204
1205! simplified comparisons only on time
1206ELEMENTAL FUNCTION ttr_mapper_eq(this, that) RESULT(res)
1207TYPE(ttr_mapper),INTENT(IN) :: this, that
1208LOGICAL :: res
1209
1210res = this%time == that%time
1211
1212END FUNCTION ttr_mapper_eq
1213
1214ELEMENTAL FUNCTION ttr_mapper_ne(this, that) RESULT(res)
1215TYPE(ttr_mapper),INTENT(IN) :: this, that
1216LOGICAL :: res
1217
1218res = this%time /= that%time
1219
1220END FUNCTION ttr_mapper_ne
1221
1222ELEMENTAL FUNCTION ttr_mapper_gt(this, that) RESULT(res)
1223TYPE(ttr_mapper),INTENT(IN) :: this, that
1224LOGICAL :: res
1225
1226res = this%time > that%time
1227
1228END FUNCTION ttr_mapper_gt
1229
1230ELEMENTAL FUNCTION ttr_mapper_lt(this, that) RESULT(res)
1231TYPE(ttr_mapper),INTENT(IN) :: this, that
1232LOGICAL :: res
1233
1234res = this%time < that%time
1235
1236END FUNCTION ttr_mapper_lt
1237
1238ELEMENTAL FUNCTION ttr_mapper_ge(this, that) RESULT(res)
1239TYPE(ttr_mapper),INTENT(IN) :: this, that
1240LOGICAL :: res
1241
1242res = this%time >= that%time
1243
1244END FUNCTION ttr_mapper_ge
1245
1246ELEMENTAL FUNCTION ttr_mapper_le(this, that) RESULT(res)
1247TYPE(ttr_mapper),INTENT(IN) :: this, that
1248LOGICAL :: res
1249
1250res = this%time <= that%time
1251
1252END FUNCTION ttr_mapper_le
1253
1254#include "arrayof_post.F90"
1255#include "array_utilities_inc.F90"
1256
1257
1258! common operations for statistical processing by differences
1259SUBROUTINE recompute_stat_proc_diff_common(itime, itimerange, stat_proc, step, &
1260 otime, otimerange, map_tr, f, keep_tr, time_definition, full_steps, &
1261 start)
1262TYPE(datetime),INTENT(in) :: itime(:)
1263TYPE(vol7d_timerange),INTENT(in) :: itimerange(:)
1264INTEGER,INTENT(in) :: stat_proc
1265TYPE(timedelta),INTENT(in) :: step
1266TYPE(datetime),POINTER :: otime(:)
1267TYPE(vol7d_timerange),POINTER :: otimerange(:)
1268INTEGER,ALLOCATABLE,INTENT(out) :: map_tr(:,:,:,:,:), f(:), keep_tr(:,:,:)
1269INTEGER :: nitr
1270LOGICAL,ALLOCATABLE :: mask_timerange(:)
1271INTEGER,INTENT(in) :: time_definition
1272LOGICAL,INTENT(in),OPTIONAL :: full_steps
1273TYPE(datetime),INTENT(in),OPTIONAL :: start
1274
1275INTEGER :: i, j, k, l, dirtyrep
1276INTEGER :: steps
1277LOGICAL :: lfull_steps, useful
1278TYPE(datetime) :: lstart, tmptime ! pstart1, pstart2, pend1, pend2, reftime1, reftime2
1279TYPE(vol7d_timerange) :: tmptimerange
1280TYPE(arrayof_datetime) :: a_otime
1281TYPE(arrayof_vol7d_timerange) :: a_otimerange
1282TYPE(timedelta) :: start_delta
1283TYPE(ttr_decoder),ALLOCATABLE :: ttr_d(:,:)
1284
1285! compute length of cumulation step in seconds
1286CALL getval(step, asec=steps)
1287
1288lstart = datetime_miss
1289IF (PRESENT(start)) lstart = start
1290lfull_steps = optio_log(full_steps)
1291
1292! create a mask of suitable timeranges
1293ALLOCATE(mask_timerange(SIZE(itimerange)))
1294mask_timerange(:) = itimerange(:)%timerange == stat_proc &
1295 .AND. itimerange(:)%p1 /= imiss .AND. itimerange(:)%p2 /= imiss &
1296 .AND. itimerange(:)%p1 >= 0 &
1297 .AND. itimerange(:)%p2 > 0
1298
1299IF (lfull_steps .AND. steps /= 0) THEN ! keep only timeranges defining intervals ending at integer forecast steps or analysis timeranges
1300 mask_timerange(:) = mask_timerange(:) .AND. &
1301 (itimerange(:)%p1 == 0 .OR. & ! all analyses
1302 mod(itimerange(:)%p1, steps) == 0 .OR. & ! end time is mod step
1303 mod(itimerange(:)%p1 - itimerange(:)%p2, steps) == 0) ! start time is mod step
1304ENDIF
1305! mask_timerange includes all candidate timeranges
1306
1307nitr = count(mask_timerange)
1308ALLOCATE(f(nitr))
1309j = 1
1310DO i = 1, nitr
1311 DO WHILE(.NOT.mask_timerange(j))
1312 j = j + 1
1313 ENDDO
1314 f(i) = j
1315 j = j + 1
1316ENDDO
1317
1318ALLOCATE(map_tr(nitr, SIZE(itime), nitr, SIZE(itime), 2))
1319map_tr(:,:,:,:,:) = imiss
1320
1321! precompute ttr
1322ALLOCATE(ttr_d(nitr,SIZE(itime)))
1323DO l = 1, SIZE(itime)
1324 DO k = 1, nitr
1325 CALL ttr_decoder_decode(itime(l), itimerange(f(k)), &
1326 time_definition, ttr_d(k,l))
1327 IF (ttr_d(k,l)%reftime == ttr_d(k,l)%pend) ttr_d(k,l)%isana = .true.
1328 ENDDO
1329ENDDO
1330
1331! now we have to evaluate time/timerage pairs which do not need processing
1332ALLOCATE(keep_tr(nitr, SIZE(itime), 2))
1333CALL compute_keep_tr()
1334
1335! scan through all possible combinations of time and timerange
1336DO dirtyrep = 1, 2
1337 IF (dirtyrep == 2) THEN ! dirty and expensive trick for sorting descriptors
1338 CALL packarray(a_otime)
1339 CALL packarray(a_otimerange)
1340 CALL sort(a_otime%array)
1341 CALL sort(a_otimerange%array)
1342 ENDIF
1343 DO l = 1, SIZE(itime)
1344 DO k = 1, nitr
1345! CALL time_timerange_get_period(itime(l), itimerange(f(k)), &
1346! time_definition, pstart2, pend2, reftime2)
1347
1348 DO j = 1, SIZE(itime)
1349 DO i = 1, nitr
1350 useful = .false.
1351! CALL time_timerange_get_period(itime(j), itimerange(f(i)), &
1352! time_definition, pstart1, pend1, reftime1)
1353! tmptimerange = vol7d_timerange_new(timerange=stat_proc)
1354
1355! IF (ttr_d(k,l)%reftime == ttr_d(k,l)%pend .AND. ttr_d(i,j)%reftime == ttr_d(i,j)%pend) THEN ! analysis
1356 IF (ttr_d(k,l)%isana .AND. ttr_d(i,j)%isana) THEN ! analysis
1357 IF (ttr_d(k,l)%pstart == ttr_d(i,j)%pstart .AND. ttr_d(k,l)%pend > ttr_d(i,j)%pend) THEN ! =-|
1358 CALL time_timerange_set_period(tmptime, tmptimerange, &
1359 time_definition, stat_proc, ttr_d(i,j)%pend, ttr_d(k,l)%pend, ttr_d(k,l)%reftime)
1360 IF (lfull_steps) THEN
1361 IF (mod(ttr_d(k,l)%reftime, step) == timedelta_0) THEN
1362 useful = .true.
1363 ENDIF
1364 ELSE
1365 useful = .true.
1366 ENDIF
1367! keep only data after lstart
1368 IF (c_e(lstart)) THEN
1369 IF (lstart > ttr_d(i,j)%pend) useful = .false.
1370 ENDIF
1371
1372 ELSE IF (ttr_d(k,l)%pstart < ttr_d(i,j)%pstart .AND. ttr_d(k,l)%pend == ttr_d(i,j)%pend) THEN ! -=|
1373 CALL time_timerange_set_period(tmptime, tmptimerange, &
1374 time_definition, stat_proc, ttr_d(k,l)%pstart, ttr_d(i,j)%pstart, ttr_d(i,j)%pstart)
1375 IF (lfull_steps) THEN
1376 IF (mod(ttr_d(i,j)%pstart, step) == timedelta_0) THEN
1377 useful = .true.
1378 ENDIF
1379 ELSE
1380 useful = .true.
1381 ENDIF
1382! keep only data after lstart
1383 IF (c_e(lstart)) THEN
1384 IF (lstart > ttr_d(k,l)%pstart) useful = .false.
1385 ENDIF
1386 ENDIF
1387
1388 ELSE IF (ttr_d(k,l)%reftime == ttr_d(i,j)%reftime) THEN ! forecast, same reftime
1389 IF (lfull_steps) THEN
1390 IF (c_e(lstart)) THEN
1391! lstart shifts the interval for computing modulo step, this does not
1392! remove data before lstart but just shifts the phase
1393 start_delta = lstart-ttr_d(k,l)%reftime
1394 ELSE
1395 start_delta = timedelta_0
1396 ENDIF
1397 ENDIF
1398
1399 IF (ttr_d(k,l)%pstart == ttr_d(i,j)%pstart .AND. ttr_d(k,l)%pend > ttr_d(i,j)%pend) THEN ! |=-
1400 CALL time_timerange_set_period(tmptime, tmptimerange, &
1401 time_definition, stat_proc, ttr_d(i,j)%pend, ttr_d(k,l)%pend, ttr_d(k,l)%reftime)
1402 IF (lfull_steps) THEN
1403 IF (mod(ttr_d(k,l)%pend-ttr_d(k,l)%reftime-start_delta, step) == timedelta_0) THEN
1404 useful = .true.
1405 ENDIF
1406 ELSE
1407 useful = .true.
1408 ENDIF
1409! keep only data after lstart
1410 IF (c_e(lstart)) THEN
1411 IF (lstart > ttr_d(i,j)%pend) useful = .false.
1412 ENDIF
1413
1414 ELSE IF (ttr_d(k,l)%pstart < ttr_d(i,j)%pstart .AND. ttr_d(k,l)%pend == ttr_d(i,j)%pend) THEN ! |-=
1415 CALL time_timerange_set_period(tmptime, tmptimerange, &
1416 time_definition, stat_proc, ttr_d(k,l)%pstart, ttr_d(i,j)%pstart, ttr_d(k,l)%reftime)
1417 IF (lfull_steps) THEN
1418 IF (mod(ttr_d(i,j)%pstart-ttr_d(k,l)%reftime-start_delta, step) == timedelta_0) THEN
1419 useful = .true.
1420 ENDIF
1421 ELSE
1422 useful = .true.
1423 ENDIF
1424! keep only data after lstart
1425 IF (c_e(lstart)) THEN
1426 IF (lstart > ttr_d(k,l)%pstart) useful = .false.
1427 ENDIF
1428
1429 ENDIF
1430 ENDIF
1431 useful = useful .AND. tmptime /= datetime_miss .AND. &
1432 tmptimerange /= vol7d_timerange_miss .AND. tmptimerange%p2 == steps
1433
1434 IF (useful) THEN ! add a_otime, a_otimerange
1435 map_tr(i,j,k,l,1) = append_unique(a_otime, tmptime)
1436 map_tr(i,j,k,l,2) = append_unique(a_otimerange, tmptimerange)
1437 ENDIF
1438 ENDDO
1439 ENDDO
1440 ENDDO
1441 ENDDO
1442ENDDO
1443
1444! we have to repeat the computation with sorted arrays
1445CALL compute_keep_tr()
1446
1447otime => a_otime%array
1448otimerange => a_otimerange%array
1449! delete local objects keeping the contents
1450CALL delete(a_otime, nodealloc=.true.)
1451CALL delete(a_otimerange, nodealloc=.true.)
1452
1453#ifdef DEBUG
1454CALL l4f_log(l4f_debug, &
1455 'recompute_stat_proc_diff, map_tr: '//t2c((SIZE(map_tr,1)))//', '// &
1456 t2c((SIZE(map_tr,2)))//', '// &
1457 t2c((SIZE(map_tr,3)))//', '// &
1458 t2c((SIZE(map_tr,4))))
1459CALL l4f_log(l4f_debug, &
1460 'recompute_stat_proc_diff, map_tr: '//t2c((SIZE(map_tr))/2)//', '// &
1461 t2c(count(c_e(map_tr))/2))
1462CALL l4f_log(l4f_debug, &
1463 'recompute_stat_proc_diff, nitr: '//t2c(nitr))
1464CALL l4f_log(l4f_debug, &
1465 'recompute_stat_proc_diff, good timeranges: '//t2c(count(c_e(keep_tr))/2))
1466CALL l4f_log(l4f_debug, &
1467 'recompute_stat_proc_diff, output times: '//t2c(SIZE(otime)))
1468CALL l4f_log(l4f_debug, &
1469 'recompute_stat_proc_diff, output timeranges: '//t2c(SIZE(otimerange)))
1470#endif
1471
1472CONTAINS
1473
1474SUBROUTINE compute_keep_tr()
1475INTEGER :: start_deltas
1476
1477keep_tr(:,:,:) = imiss
1478DO l = 1, SIZE(itime)
1479 itrloop: DO k = 1, nitr
1480 IF (itimerange(f(k))%p2 == steps) THEN
1481! CALL time_timerange_get_period(itime(l), itimerange(f(k)), &
1482! time_definition, pstart2, pend2, reftime2)
1483 useful = .false.
1484! keep only data after lstart
1485 IF (c_e(lstart)) THEN
1486 IF (lstart > ttr_d(k,l)%pstart) cycle itrloop
1487 ENDIF
1488 IF (ttr_d(k,l)%reftime == ttr_d(k,l)%pend) THEN ! analysis
1489 IF (c_e(lstart)) THEN ! in analysis mode start wins over full_steps
1490 IF (mod(ttr_d(k,l)%reftime-lstart, step) == timedelta_0) THEN
1491 useful = .true.
1492 ENDIF
1493 ELSE IF (lfull_steps) THEN
1494 IF (mod(ttr_d(k,l)%reftime, step) == timedelta_0) THEN
1495 useful = .true.
1496 ENDIF
1497 ELSE
1498 useful = .true.
1499 ENDIF
1500 ELSE ! forecast
1501 IF (lfull_steps) THEN
1502! same as above for start_delta, but in seconds and not in timerange/timedelta units
1503 IF (c_e(lstart)) THEN
1504 start_deltas = timedelta_getamsec(lstart-ttr_d(k,l)%reftime)/1000_int_ll
1505 ELSE
1506 start_deltas = 0
1507 ENDIF
1508 IF (mod(itimerange(f(k))%p1 - start_deltas, steps) == 0) THEN
1509 useful = .true.
1510 ENDIF
1511 ELSE
1512 useful = .true.
1513 ENDIF
1514 ENDIF
1515 IF (useful) THEN
1516! CALL time_timerange_set_period(tmptime, tmptimerange, &
1517! time_definition, stat_proc, pstart2, pend2, reftime2)
1518 keep_tr(k,l,1) = append_unique(a_otime, itime(l))
1519 keep_tr(k,l,2) = append_unique(a_otimerange, itimerange(f(k)))
1520 ENDIF
1521 ENDIF
1522 ENDDO itrloop
1523ENDDO
1524
1525END SUBROUTINE compute_keep_tr
1526
1527END SUBROUTINE recompute_stat_proc_diff_common
1528
1529
1530! common operations for statistical processing by metamorphosis
1531SUBROUTINE compute_stat_proc_metamorph_common(istat_proc, itimerange, ostat_proc, &
1532 otimerange, map_tr)
1533INTEGER,INTENT(in) :: istat_proc
1534TYPE(vol7d_timerange),INTENT(in) :: itimerange(:)
1535INTEGER,INTENT(in) :: ostat_proc
1536TYPE(vol7d_timerange),POINTER :: otimerange(:)
1537INTEGER,POINTER :: map_tr(:)
1538
1539INTEGER :: i
1540LOGICAL :: tr_mask(SIZE(itimerange))
1541
1542IF (SIZE(itimerange) == 0) THEN ! avoid segmentation fault in case of empty volume
1543 ALLOCATE(otimerange(0), map_tr(0))
1544 RETURN
1545ENDIF
1546
1547! useful timeranges
1548tr_mask(:) = itimerange(:)%timerange == istat_proc .AND. itimerange(:)%p2 /= imiss &
1549 .AND. itimerange(:)%p2 /= 0 ! .AND. itimerange(:)%p1 == 0
1550ALLOCATE(otimerange(count(tr_mask)), map_tr(count(tr_mask)))
1551
1552otimerange = pack(itimerange, mask=tr_mask)
1553otimerange(:)%timerange = ostat_proc
1554map_tr = pack((/(i,i=1,SIZE(itimerange))/), mask=tr_mask)
1555
1556END SUBROUTINE compute_stat_proc_metamorph_common
1557
1558
1559! common operations for statistical processing by aggregation
1560SUBROUTINE recompute_stat_proc_agg_common(itime, itimerange, stat_proc, tri, &
1561 step, time_definition, otime, otimerange, map_ttr, dtratio, start, full_steps)
1562TYPE(datetime),INTENT(in) :: itime(:)
1563TYPE(vol7d_timerange),INTENT(in) :: itimerange(:)
1564INTEGER,INTENT(in) :: stat_proc
1565INTEGER,INTENT(in) :: tri
1566TYPE(timedelta),INTENT(in) :: step
1567INTEGER,INTENT(in) :: time_definition
1568TYPE(datetime),POINTER :: otime(:)
1569TYPE(vol7d_timerange),POINTER :: otimerange(:)
1570TYPE(arrayof_ttr_mapper),POINTER :: map_ttr(:,:)
1571INTEGER,POINTER,OPTIONAL :: dtratio(:)
1572TYPE(datetime),INTENT(in),OPTIONAL :: start
1573LOGICAL,INTENT(in),OPTIONAL :: full_steps
1574
1575INTEGER :: i, j, k, l, na, nf, n
1576INTEGER :: steps, p1, maxp1, maxp2, minp1mp2, dstart, msteps
1577INTEGER(kind=int_ll) :: stepms, mstepms
1578LOGICAL :: lforecast
1579TYPE(datetime) :: lstart, lend, pstart1, pstart2, pend1, pend2, reftime1, reftime2, tmptime
1580TYPE(arrayof_datetime) :: a_otime
1581TYPE(arrayof_vol7d_timerange) :: a_otimerange
1582TYPE(arrayof_integer) :: a_dtratio
1583LOGICAL,ALLOCATABLE :: mask_timerange(:) ! improve !!!!
1584TYPE(ttr_mapper) :: lmapper
1585CHARACTER(len=8) :: env_var
1586LOGICAL :: climat_behavior
1587
1588
1589! enable bad behavior for climat database (only for instantaneous data)
1590env_var = ''
1591CALL getenv('LIBSIM_CLIMAT_BEHAVIOR', env_var)
1592climat_behavior = len_trim(env_var) > 0 .AND. .NOT.PRESENT(dtratio)
1593
1594! compute length of cumulation step in seconds
1595CALL getval(timedelta_depop(step), asec=steps)
1596
1597! create a mask of suitable timeranges
1598ALLOCATE(mask_timerange(SIZE(itimerange)))
1599mask_timerange(:) = itimerange(:)%timerange == tri &
1600 .AND. itimerange(:)%p1 /= imiss .AND. itimerange(:)%p1 >= 0
1601
1602IF (PRESENT(dtratio)) THEN
1603 WHERE(itimerange(:)%p2 > 0 .AND. itimerange(:)%p2 /= imiss) ! for avoiding FPE MOD(steps, 0)
1604 mask_timerange(:) = mask_timerange(:) .AND. mod(steps, itimerange(:)%p2) == 0
1605 ELSEWHERE
1606 mask_timerange(:) = .false.
1607 END WHERE
1608ELSE ! instantaneous
1609 mask_timerange(:) = mask_timerange(:) .AND. itimerange(:)%p2 == 0
1610ENDIF
1611
1612#ifdef DEBUG
1613CALL l4f_log(l4f_debug, &
1614 '(re)compute_stat_proc_agg, number of useful timeranges before choosing analysis/forecast: '// &
1615 t2c(count(mask_timerange)))
1616#endif
1617
1618! euristically determine whether we are dealing with an
1619! analysis/observation or a forecast dataset
1620na = count(mask_timerange(:) .AND. itimerange(:)%p1 == 0)
1621nf = count(mask_timerange(:) .AND. itimerange(:)%p1 > 0)
1622lforecast = nf >= na
1623#ifdef DEBUG
1624CALL l4f_log(l4f_debug, &
1625 'recompute_stat_proc_agg, na: '//t2c(na)//', nf: '//t2c(nf))
1626#endif
1627
1628! keep only timeranges of one type (really necessary?)
1629IF (lforecast) THEN
1630 CALL l4f_log(l4f_info, &
1631 'recompute_stat_proc_agg, processing in forecast mode')
1632ELSE
1633 mask_timerange(:) = mask_timerange(:) .AND. itimerange(:)%p1 == 0
1634 CALL l4f_log(l4f_info, &
1635 'recompute_stat_proc_agg, processing in analysis mode')
1636ENDIF
1637
1638#ifdef DEBUG
1639CALL l4f_log(l4f_debug, &
1640 '(re)compute_stat_proc_agg, number of useful timeranges: '// &
1641 t2c(count(mask_timerange)))
1642#endif
1643
1644IF (SIZE(itime) == 0 .OR. count(mask_timerange) == 0) THEN ! avoid segmentation fault in case of empty volume
1645 ALLOCATE(otime(0), otimerange(0), map_ttr(0,0))
1646 IF (PRESENT(dtratio)) ALLOCATE(dtratio(0))
1647 RETURN
1648ENDIF
1649
1650! determine start and end of processing period, should work with p2==0
1651lstart = datetime_miss
1652IF (PRESENT(start)) lstart = start
1653lend = itime(SIZE(itime))
1654! compute some quantities
1655maxp1 = maxval(itimerange(:)%p1, mask=mask_timerange)
1656maxp2 = maxval(itimerange(:)%p2, mask=mask_timerange)
1657minp1mp2 = minval(itimerange(:)%p1 - itimerange(:)%p2, mask=mask_timerange)
1658IF (time_definition == 0) THEN ! reference time
1659 lend = lend + timedelta_new(sec=maxp1)
1660ENDIF
1661! extend interval at the end in order to include all the data in case
1662! frac_valid<1; must use < and not <= in the DO WHILE loops some lines
1663! below in order to exclude the last full interval which would be empty
1664lend = lend + step
1665IF (lstart == datetime_miss) THEN ! autodetect
1666 lstart = itime(1)
1667! if autodetected, adjust to obtain real absolute start of data
1668 IF (time_definition == 0) THEN ! reference time
1669 lstart = lstart + timedelta_new(sec=minp1mp2)
1670 ELSE ! verification time
1671! go back to start of longest processing interval
1672 lstart = lstart - timedelta_new(sec=maxp2)
1673 ENDIF
1674! apply full_steps in analysis mode and when start is not specified
1675! (start by itself in analysis mode implies full_steps with respect to
1676! start instead of absolute full steps), todo in forecast mode
1677 IF (optio_log(full_steps) .AND. .NOT.lforecast) THEN
1678 lstart = lstart - (mod(lstart, step)) ! round to step, (should be MODULO, not MOD)
1679 ENDIF
1680ENDIF
1681
1682#ifdef DEBUG
1683CALL l4f_log(l4f_debug, &
1684 'recompute_stat_proc_agg, processing period: '//t2c(lstart)//' - '//t2c(lend))
1685#endif
1686
1687! create output time and timerange lists
1688
1689IF (lforecast) THEN ! forecast mode
1690 IF (time_definition == 0) THEN ! reference time
1691 CALL insert(a_otime, itime) ! should I limit to elements itime >= lstart?
1692
1693! apply start shift to timerange, not to reftime
1694! why did we use itime(SIZE(itime)) (last ref time)?
1695! CALL getval(lstart-itime(SIZE(itime)), asec=dstart)
1696 CALL getval(lstart-itime(1), asec=dstart)
1697! allow starting before first reftime but restrict dtstart to -steps
1698! dstart = MAX(0, dstart)
1699 IF (dstart < 0) dstart = mod(dstart, steps)
1700 DO p1 = steps + dstart, maxp1, steps
1701 CALL insert_unique(a_otimerange, vol7d_timerange_new(stat_proc, p1, steps))
1702 ENDDO
1703
1704 ELSE ! verification time
1705
1706! verification time in forecast mode is the ugliest case, because we
1707! don't know a priori how many different (thus incompatible) reference
1708! times we have, so some assumption of regularity has to be made. For
1709! this reason msteps, the minimum step between two times, is
1710! computed. We choose to compute it as a difference between itime
1711! elements, it could be also computed as difference of itimerange%p1
1712! elements. But what if it is not modulo steps?
1713 mstepms = steps*1000_int_ll
1714 DO i = 2, SIZE(itime)
1715 CALL getval(itime(i)-itime(i-1), amsec=stepms)
1716 IF (stepms > 0_int_ll .AND. stepms < mstepms) THEN
1717 msteps = stepms/1000_int_ll
1718 IF (mod(steps, msteps) == 0) mstepms = stepms
1719 ENDIF
1720 ENDDO
1721 msteps = mstepms/1000_int_ll
1722
1723 tmptime = lstart + step
1724 DO WHILE(tmptime < lend) ! < since lend has been extended
1725 CALL insert_unique(a_otime, tmptime)
1726 tmptime = tmptime + step
1727 ENDDO
1728
1729! in next loop, we used initially steps instead of msteps (see comment
1730! above), this gave much less combinations of time/timeranges with
1731! possible empty output; we start from msteps instead of steps in
1732! order to include partial initial intervals in case frac_valid<1;
1733! however, as a gemeral rule, for aggregation of forecasts it's better
1734! to use reference time
1735 DO p1 = msteps, maxp1, msteps
1736 CALL insert_unique(a_otimerange, vol7d_timerange_new(stat_proc, p1, steps))
1737 ENDDO
1738
1739 ENDIF
1740
1741ELSE ! analysis mode
1742 tmptime = lstart + step
1743 DO WHILE(tmptime < lend) ! < since lend has been extended
1744 CALL insert_unique(a_otime, tmptime)
1745 tmptime = tmptime + step
1746 ENDDO
1747 CALL insert_unique(a_otimerange, vol7d_timerange_new(stat_proc, 0, steps))
1748
1749ENDIF
1750
1751CALL packarray(a_otime)
1752CALL packarray(a_otimerange)
1753otime => a_otime%array
1754otimerange => a_otimerange%array
1755CALL sort(otime)
1756CALL sort(otimerange)
1757! delete local objects keeping the contents
1758CALL delete(a_otime, nodealloc=.true.)
1759CALL delete(a_otimerange, nodealloc=.true.)
1760
1761#ifdef DEBUG
1762CALL l4f_log(l4f_debug, &
1763 'recompute_stat_proc_agg, output time and timerange: '//&
1764 t2c(SIZE(otime))//', '//t2c(size(otimerange)))
1765#endif
1766
1767IF (PRESENT(dtratio)) THEN
1768! count the possible i/o interval ratios
1769 DO k = 1, SIZE(itimerange)
1770 IF (itimerange(k)%p2 /= 0) &
1771 CALL insert_unique(a_dtratio, steps/itimerange(k)%p2) ! guaranteed to be integer
1772 ENDDO
1773 CALL packarray(a_dtratio)
1774 dtratio => a_dtratio%array
1775 CALL sort(dtratio)
1776! delete local object keeping the contents
1777 CALL delete(a_dtratio, nodealloc=.true.)
1778
1779#ifdef DEBUG
1780 CALL l4f_log(l4f_debug, &
1781 'recompute_stat_proc_agg, found '//t2c(size(dtratio))// &
1782 ' possible aggregation ratios, from '// &
1783 t2c(dtratio(1))//' to '//t2c(dtratio(SIZE(dtratio))))
1784#endif
1785
1786 ALLOCATE(map_ttr(SIZE(otime),SIZE(otimerange)))
1787 do_itimerange1: DO l = 1, SIZE(itimerange)
1788 IF (.NOT.mask_timerange(l)) cycle do_itimerange1
1789 do_itime1: DO k = 1, SIZE(itime)
1790 CALL time_timerange_get_period(itime(k), itimerange(l), &
1791 time_definition, pstart1, pend1, reftime1)
1792 do_otimerange1: DO j = 1, SIZE(otimerange)
1793 do_otime1: DO i = 1, SIZE(otime)
1794 CALL time_timerange_get_period_pop(otime(i), otimerange(j), step, &
1795 time_definition, pstart2, pend2, reftime2)
1796 IF (lforecast) THEN
1797 IF (reftime1 /= reftime2) cycle do_otime1
1798 ENDIF
1799
1800 IF (pstart1 >= pstart2 .AND. pend1 <= pend2 .AND. &
1801 mod(pstart1-pstart2, pend1-pstart1) == timedelta_0) THEN ! useful
1802 lmapper%it = k
1803 lmapper%itr = l
1804 lmapper%extra_info = steps/itimerange(l)%p2 ! dtratio, guaranteed to be integer
1805 n = append(map_ttr(i,j), lmapper)
1806 cycle do_itime1 ! can contribute only to a single interval
1807 ENDIF
1808 ENDDO do_otime1
1809 ENDDO do_otimerange1
1810 ENDDO do_itime1
1811 ENDDO do_itimerange1
1812
1813ELSE
1814
1815 ALLOCATE(map_ttr(SIZE(otime),SIZE(otimerange)))
1816 do_itimerange2: DO l = 1, SIZE(itimerange)
1817 IF (.NOT.mask_timerange(l)) cycle do_itimerange2
1818 do_itime2: DO k = 1, SIZE(itime)
1819 CALL time_timerange_get_period(itime(k), itimerange(l), &
1820 time_definition, pstart1, pend1, reftime1)
1821 do_otimerange2: DO j = 1, SIZE(otimerange)
1822 do_otime2: DO i = 1, SIZE(otime)
1823 CALL time_timerange_get_period_pop(otime(i), otimerange(j), step, &
1824 time_definition, pstart2, pend2, reftime2)
1825 IF (lforecast) THEN
1826 IF (reftime1 /= reftime2) cycle do_otime2
1827 ENDIF
1828
1829 IF (climat_behavior .AND. pstart1 == pstart2) cycle do_otime2
1830 IF (pstart1 >= pstart2 .AND. pend1 <= pend2) THEN ! useful
1831 lmapper%it = k
1832 lmapper%itr = l
1833 IF (pstart1 == pstart2) THEN
1834 lmapper%extra_info = 1 ! start of interval
1835 ELSE IF (pend1 == pend2) THEN
1836 lmapper%extra_info = 2 ! end of interval
1837 ELSE
1838 lmapper%extra_info = imiss
1839 ENDIF
1840 lmapper%time = pstart1 ! = pend1, order by time?
1841 n = insert_sorted(map_ttr(i,j), lmapper, .true., .true.)
1842! no CYCLE, a single input can contribute to multiple output intervals
1843 ENDIF
1844 ENDDO do_otime2
1845 ENDDO do_otimerange2
1846 ENDDO do_itime2
1847 ENDDO do_itimerange2
1848
1849ENDIF
1850
1851END SUBROUTINE recompute_stat_proc_agg_common
1852
1853
1854SUBROUTINE compute_stat_proc_agg_sw(vertime, pstart, pend, time_mask, &
1855 max_step, weights)
1856TYPE(datetime),INTENT(in) :: vertime(:)
1857TYPE(datetime),INTENT(in) :: pstart
1858TYPE(datetime),INTENT(in) :: pend
1859LOGICAL,INTENT(in) :: time_mask(:)
1860TYPE(timedelta),OPTIONAL,INTENT(out) :: max_step
1861DOUBLE PRECISION,OPTIONAL,INTENT(out) :: weights(:)
1862
1863INTEGER :: i, nt
1864TYPE(datetime),ALLOCATABLE :: lvertime(:)
1865TYPE(datetime) :: half, nexthalf
1866INTEGER(kind=int_ll) :: dt, tdt
1867
1868nt = count(time_mask)
1869ALLOCATE(lvertime(nt))
1870lvertime = pack(vertime, mask=time_mask)
1871
1872IF (PRESENT(max_step)) THEN
1873! new way
1874! max_step = timedelta_0
1875! DO i = 1, nt - 1
1876! IF (lvertime(i+1) - lvertime(i) > max_step) &
1877! max_step = lvertime(i+1) - lvertime(i)
1878! ENDDO
1879! IF (lvertime(1) - pstart > max_step) max_step = lvertime(1) - pstart
1880! IF (pend - lvertime(nt) > max_step) max_step = pend - lvertime(nt)
1881! old way
1882 IF (nt == 1) THEN
1883 max_step = pend - pstart
1884 ELSE
1885 half = lvertime(1) + (lvertime(2) - lvertime(1))/2
1886 max_step = half - pstart
1887 DO i = 2, nt - 1
1888 nexthalf = lvertime(i) + (lvertime(i+1) - lvertime(i))/2
1889 IF (nexthalf - half > max_step) max_step = nexthalf - half
1890 half = nexthalf
1891 ENDDO
1892 IF (pend - half > max_step) max_step = pend - half
1893 ENDIF
1894
1895ENDIF
1896
1897IF (PRESENT(weights)) THEN
1898 IF (nt == 1) THEN
1899 weights(1) = 1.0
1900 ELSE
1901 CALL getval(pend - pstart, amsec=tdt)
1902 half = lvertime(1) + (lvertime(2) - lvertime(1))/2
1903 CALL getval(half - pstart, amsec=dt)
1904 weights(1) = dble(dt)/dble(tdt)
1905 DO i = 2, nt - 1
1906 nexthalf = lvertime(i) + (lvertime(i+1) - lvertime(i))/2
1907 CALL getval(nexthalf - half, amsec=dt)
1908 weights(i) = dble(dt)/dble(tdt)
1909 half = nexthalf
1910 ENDDO
1911 CALL getval(pend - half, amsec=dt)
1912 weights(nt) = dble(dt)/dble(tdt)
1913 ENDIF
1914ENDIF
1915
1916END SUBROUTINE compute_stat_proc_agg_sw
1917
1918! get start of period, end of period and reference time from time,
1919! timerange, according to time_definition.
1920SUBROUTINE time_timerange_get_period(time, timerange, time_definition, &
1921 pstart, pend, reftime)
1922TYPE(datetime),INTENT(in) :: time
1923TYPE(vol7d_timerange),INTENT(in) :: timerange
1924INTEGER,INTENT(in) :: time_definition
1925TYPE(datetime),INTENT(out) :: reftime
1926TYPE(datetime),INTENT(out) :: pstart
1927TYPE(datetime),INTENT(out) :: pend
1928
1929TYPE(timedelta) :: p1, p2
1930
1931
1932p1 = timedelta_new(sec=timerange%p1) ! end of period
1933p2 = timedelta_new(sec=timerange%p2) ! length of period
1934
1935IF (time == datetime_miss .OR. .NOT.c_e(timerange%p1) .OR. .NOT.c_e(timerange%p2) .OR. &
1936! (timerange%p1 > 0 .AND. timerange%p1 < timerange%p2) .OR. &
1937 timerange%p1 < 0 .OR. timerange%p2 < 0) THEN ! is this too pedantic and slow?
1938 pstart = datetime_miss
1939 pend = datetime_miss
1940 reftime = datetime_miss
1941 RETURN
1942ENDIF
1943
1944IF (time_definition == 0) THEN ! time == reference time
1945 reftime = time
1946 pend = time + p1
1947 pstart = pend - p2
1948ELSE IF (time_definition == 1 .OR. time_definition == 2) THEN ! time == verification time
1949 pend = time
1950 pstart = time - p2
1951 reftime = time - p1
1952ELSE
1953 pstart = datetime_miss
1954 pend = datetime_miss
1955 reftime = datetime_miss
1956ENDIF
1957
1958END SUBROUTINE time_timerange_get_period
1959
1960
1961! get start of period, end of period and reference time from time,
1962! timerange, according to time_definition.
1963SUBROUTINE ttr_decoder_decode(time, timerange, time_definition, decoded)
1964TYPE(datetime),INTENT(in) :: time
1965TYPE(vol7d_timerange),INTENT(in) :: timerange
1966INTEGER,INTENT(in) :: time_definition
1967TYPE(ttr_decoder),INTENT(out) :: decoded
1968
1969TYPE(timedelta) :: p1, p2
1970
1971
1972p1 = timedelta_new(sec=timerange%p1) ! end of period
1973p2 = timedelta_new(sec=timerange%p2) ! length of period
1974
1975IF (time == datetime_miss .OR. .NOT.c_e(timerange%p1) .OR. .NOT.c_e(timerange%p2) .OR. &
1976! (timerange%p1 > 0 .AND. timerange%p1 < timerange%p2) .OR. &
1977 timerange%p1 < 0 .OR. timerange%p2 < 0) THEN ! is this too pedantic and slow?
1978 decoded%pstart = datetime_miss
1979 decoded%pend = datetime_miss
1980 decoded%reftime = datetime_miss
1981 RETURN
1982ENDIF
1983
1984IF (time_definition == 0) THEN ! time == reference time
1985 decoded%reftime = time
1986 decoded%pend = time + p1
1987 decoded%pstart = decoded%pend - p2
1988ELSE IF (time_definition == 1 .OR. time_definition == 2) THEN ! time == verification time
1989 decoded%pend = time
1990 decoded%pstart = time - p2
1991 decoded%reftime = time - p1
1992ELSE
1993 decoded%pstart = datetime_miss
1994 decoded%pend = datetime_miss
1995 decoded%reftime = datetime_miss
1996ENDIF
1997
1998END SUBROUTINE ttr_decoder_decode
1999
2000
2001! get start of period, end of period and reference time from time,
2002! timerange, according to time_definition. step is taken separately
2003! from timerange and can be "popular"
2004SUBROUTINE time_timerange_get_period_pop(time, timerange, step, time_definition, &
2005 pstart, pend, reftime)
2006TYPE(datetime),INTENT(in) :: time
2007TYPE(vol7d_timerange),INTENT(in) :: timerange
2008TYPE(timedelta),INTENT(in) :: step
2009INTEGER,INTENT(in) :: time_definition
2010TYPE(datetime),INTENT(out) :: reftime
2011TYPE(datetime),INTENT(out) :: pstart
2012TYPE(datetime),INTENT(out) :: pend
2013
2014TYPE(timedelta) :: p1
2015
2016
2017p1 = timedelta_new(sec=timerange%p1) ! end of period
2018
2019IF (time == datetime_miss .OR. .NOT.c_e(timerange%p1) .OR. .NOT.c_e(timerange%p2) .OR. &
2020! (timerange%p1 > 0 .AND. timerange%p1 < timerange%p2) .OR. &
2021 timerange%p1 < 0 .OR. timerange%p2 < 0) THEN ! is this too pedantic and slow?
2022 pstart = datetime_miss
2023 pend = datetime_miss
2024 reftime = datetime_miss
2025 RETURN
2026ENDIF
2027
2028IF (time_definition == 0) THEN ! time == reference time
2029 reftime = time
2030 pend = time + p1
2031 pstart = pend - step
2032ELSE IF (time_definition == 1 .OR. time_definition == 2) THEN ! time == verification time
2033 pend = time
2034 pstart = time - step
2035 reftime = time - p1
2036ELSE
2037 pstart = datetime_miss
2038 pend = datetime_miss
2039 reftime = datetime_miss
2040ENDIF
2041
2042END SUBROUTINE time_timerange_get_period_pop
2043
2044
2045! get start of period, end of period and reference time from time,
2046! timerange, according to time_definition. step is taken separately
2047! from timerange and can be "popular"
2048SUBROUTINE ttr_decoder_decode_pop(time, timerange, step, time_definition, decoded)
2049TYPE(datetime),INTENT(in) :: time
2050TYPE(vol7d_timerange),INTENT(in) :: timerange
2051TYPE(timedelta),INTENT(in) :: step
2052INTEGER,INTENT(in) :: time_definition
2053TYPE(ttr_decoder),INTENT(out) :: decoded
2054
2055TYPE(timedelta) :: p1
2056
2057
2058p1 = timedelta_new(sec=timerange%p1) ! end of period
2059
2060IF (time == datetime_miss .OR. .NOT.c_e(timerange%p1) .OR. .NOT.c_e(timerange%p2) .OR. &
2061! (timerange%p1 > 0 .AND. timerange%p1 < timerange%p2) .OR. &
2062 timerange%p1 < 0 .OR. timerange%p2 < 0) THEN ! is this too pedantic and slow?
2063 decoded%pstart = datetime_miss
2064 decoded%pend = datetime_miss
2065 decoded%reftime = datetime_miss
2066 RETURN
2067ENDIF
2068
2069IF (time_definition == 0) THEN ! time == reference time
2070 decoded%reftime = time
2071 decoded%pend = time + p1
2072 decoded%pstart = decoded%pend - step
2073ELSE IF (time_definition == 1 .OR. time_definition == 2) THEN ! time == verification time
2074 decoded%pend = time
2075 decoded%pstart = time - step
2076 decoded%reftime = time - p1
2077ELSE
2078 decoded%pstart = datetime_miss
2079 decoded%pend = datetime_miss
2080 decoded%reftime = datetime_miss
2081ENDIF
2082
2083END SUBROUTINE ttr_decoder_decode_pop
2084
2085
2086! set time, timerange%p1, timerange%p2 according to pstart, pend,
2087! reftime and time_definition.
2088SUBROUTINE time_timerange_set_period(time, timerange, time_definition, &
2089 stat_proc, pstart, pend, reftime)
2090TYPE(datetime),INTENT(out) :: time
2091TYPE(vol7d_timerange),INTENT(out) :: timerange
2092INTEGER,INTENT(in) :: time_definition
2093INTEGER,INTENT(in) :: stat_proc
2094TYPE(datetime),INTENT(in) :: pstart
2095TYPE(datetime),INTENT(in) :: pend
2096TYPE(datetime),INTENT(in) :: reftime
2097
2098TYPE(timedelta) :: p1, p2
2099INTEGER(kind=int_ll) :: dmsec
2100
2101
2102IF (time_definition == 0) THEN ! time == reference time
2103 time = reftime
2104 p1 = pend - reftime
2105 p2 = pend - pstart
2106ELSE IF (time_definition == 1 .OR. time_definition == 2) THEN ! time == verification time
2107 time = pend
2108 p1 = pend - reftime
2109 p2 = pend - pstart
2110ELSE
2111 time = datetime_miss
2112ENDIF
2113
2114timerange%timerange = stat_proc
2115IF (time /= datetime_miss) THEN
2116 CALL getval(p1, amsec=dmsec) ! end of period
2117 timerange%p1 = int(dmsec/1000_int_ll)
2118 CALL getval(p2, amsec=dmsec) ! length of period
2119 timerange%p2 = int(dmsec/1000_int_ll)
2120ELSE
2121 timerange%p1 = imiss
2122 timerange%p2 = imiss
2123ENDIF
2124
2125END SUBROUTINE time_timerange_set_period
2126
2127
2128END MODULE stat_proc_engine
Restituiscono il valore dell'oggetto nella forma desiderata.
Operatore di resto della divisione.
Functions that return a trimmed CHARACTER representation of the input variable.
Quick method to append an element to the array.
Destructor for finalizing an array object.
Method for inserting elements of the array at a desired position.
Method for packing the array object reducing at a minimum the memory occupation, without destroying i...
Classi per la gestione delle coordinate temporali.
This module contains functions that are only for internal use of the library.
Classe per la gestione di un volume completo di dati osservati.

Generated with Doxygen.