libsim Versione 8.0.0

◆ index_ttr_mapper()

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

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

Definizione alla linea 1302 del file stat_proc_engine.F90.

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