Branch data Line data Source code
1 : : // *****************************************************************************
2 : : /*!
3 : : \file src/Base/Timer.cpp
4 : : \copyright 2012-2015 J. Bakosi,
5 : : 2016-2018 Los Alamos National Security, LLC.,
6 : : 2019-2021 Triad National Security, LLC.,
7 : : 2022-2025 J. Bakosi
8 : : All rights reserved. See the LICENSE file for details.
9 : : \brief Timer definition
10 : : \details Timer definition. Timer is a simple class to do timing various
11 : : parts of the code in a portable way. The functionality is intended to be
12 : : very minimal and simple, but still convenient to use, with as little state
13 : : as possible. For an example client code, see Main.
14 : : */
15 : : // *****************************************************************************
16 : :
17 : : #include <algorithm>
18 : : #include <ratio>
19 : : #include <cmath>
20 : :
21 : : #include "Timer.hpp"
22 : : #include "Exception.hpp"
23 : :
24 : : using tk::Timer;
25 : :
26 : : tk::Timer::Watch
27 : 567 : Timer::hms() const
28 : : // *****************************************************************************
29 : : // Return time elapsed between start and stop for timer as hours, minutes, and
30 : : // seconds.
31 : : //! \return Time elapsed between start and stop as hours, minutes, and seconds,
32 : : //! as a Watch struct.
33 : : // *****************************************************************************
34 : : {
35 : : using std::chrono::duration_cast;
36 : :
37 : : // Compute time difference between start and now in seconds
38 [ + - ][ + - ]: 567 : Dsec elapsed = clock::now() - m_start;
39 : :
40 : : // Put elapsed time in watch as hours:minutes:seconds
41 [ + - ]: 567 : Watch watch( duration_cast< hours >( elapsed ),
42 [ + - ][ + - ]: 567 : duration_cast< minutes >( elapsed ) % hours(1),
43 [ + - ][ + - ]: 1134 : duration_cast< seconds >( elapsed ) % minutes(1) );
44 : 1134 : return watch;
45 : : }
46 : :
47 : : void
48 : 3063 : Timer::eta( tk::real term, tk::real time, uint64_t nstep, uint64_t it,
49 : : tk::real res0, tk::real res, tk::real rest,
50 : : Watch& elapsedWatch, Watch& estimatedWatch )
51 : : // *****************************************************************************
52 : : // Estimate time for accomplishment
53 : : //! \param[in] term Time at which to terminate time stepping
54 : : //! \param[in] time Current time
55 : : //! \param[in] nstep Max number of time steps to take
56 : : //! \param[in] it Current iteration count
57 : : //! \param[in] res0 Residual at previous call (during convergence to steady
58 : : //! state)
59 : : //! \param[in] res Current residual (during convergence to steady state)
60 : : //! \param[in] rest Target residual (during convergence to steady state)
61 : : //! \param[out] elapsedWatch Elapsed time in h:m:s
62 : : //! \param[out] estimatedWatch Estimated time for accomplishmet in h:m:s
63 : : // *****************************************************************************
64 : : {
65 : : using std::chrono::duration_cast;
66 : :
67 : 3063 : Dsec elapsed, estimated{};
68 : :
69 [ - + ][ - - ]: 3063 : Assert( it > 0, "it == 0" );
[ - - ][ - - ]
70 : :
71 : 3063 : tk::real eps = std::numeric_limits< real >::epsilon();
72 : :
73 : : // Compute time difference between start and now in seconds
74 [ + - ][ + - ]: 3063 : elapsed = clock::now() - m_start;
75 : :
76 [ + + ]: 3063 : if (rest > eps) {
77 : :
78 [ + + ][ + - ]: 161 : if (res0 > eps && res > eps) {
79 : : // Estimate time until convergence to steady state (assume log-lin fn)
80 : : using std::log;
81 : 151 : auto d = log(res0/res);
82 [ + - ][ + - ]: 151 : Dsec recent_elapsed = clock::now() - m_prev;
83 [ + - ]: 151 : Dsec est_res = std::abs(d) > eps ?
84 : 151 : recent_elapsed * log(res/rest) / d :
85 : 0 : Dsec(0);
86 : :
87 : : // Ignore negative estimates (temporarily non-decreasing residual)
88 [ + - ]: 151 : estimated = std::max( Dsec(0), est_res );
89 : 151 : m_prev = clock::now();
90 : : }
91 : :
92 : :
93 : : } else {
94 : :
95 : : // Estimate time until nstep in seconds (assume lin-lin fn)
96 : 2902 : Dsec est_nstep = elapsed * static_cast<tk::real>(nstep-it) / it;
97 : : // Estimate time until term in seconds (assume lin-lin fn)
98 : 2902 : tk::real large = std::numeric_limits< real >::max() - 1;
99 [ + - ][ + + ]: 2902 : Dsec est_term = std::abs(time) > eps && term < large ?
100 : 731 : elapsed * (term-time) / time :
101 : 2902 : est_nstep;
102 : :
103 : : // Time stepping will stop at term or nstep, whichever is sooner
104 : 2902 : estimated = std::min( est_term, est_nstep );
105 : : }
106 : :
107 : : // Put elapsed time in watch as hours:minutes:seconds
108 [ + - ]: 3063 : elapsedWatch.hrs = duration_cast< hours >( elapsed );
109 [ + - ][ + - ]: 3063 : elapsedWatch.min = duration_cast< minutes >( elapsed ) % hours(1);
110 [ + - ][ + - ]: 3063 : elapsedWatch.sec = duration_cast< seconds >( elapsed ) % minutes(1);
111 : : // Put estimated time in watch as hours:minutes:seconds
112 [ + - ]: 3063 : estimatedWatch.hrs = duration_cast< hours >( estimated );
113 [ + - ][ + - ]: 3063 : estimatedWatch.min = duration_cast< minutes >( estimated ) % hours(1);
114 [ + - ][ + - ]: 3063 : estimatedWatch.sec = duration_cast< seconds >( estimated ) % minutes(1);
115 : 3063 : }
116 : :
117 : : Timer::Watch
118 : 83 : tk::hms( tk::real stamp )
119 : : // *****************************************************************************
120 : : //! Convert existing time stamp as a real to Watch (global-scope)
121 : : //! \param[in] stamp Time stamp as a real number
122 : : //! \return Time as hours, minutes, and seconds, as a Watch struct.
123 : : // *****************************************************************************
124 : : {
125 : : using std::chrono::duration_cast;
126 : 83 : const auto d = Timer::Dsec( stamp );
127 : : return
128 [ + - ]: 83 : Timer::Watch( duration_cast< Timer::hours >( d ),
129 [ + - ][ + - ]: 83 : duration_cast< Timer::minutes >( d ) % Timer::hours(1),
130 [ + - ][ + - ]: 166 : duration_cast< Timer::seconds >( d ) % Timer::minutes(1) );
131 : : }
|