libsim Versione 8.0.0

◆ map_inv_distinct_ttr_mapper()

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

map inv distinct

Definizione alla linea 1216 del file stat_proc_engine.F90.

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