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