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-2024 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 : 539 : 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 : 539 : Dsec elapsed = clock::now() - m_start; 39 : : 40 : : // Put elapsed time in watch as hours:minutes:seconds 41 : : Watch watch( duration_cast< hours >( elapsed ), 42 : : duration_cast< minutes >( elapsed ) % hours(1), 43 : : duration_cast< seconds >( elapsed ) % minutes(1) ); 44 : 539 : return watch; 45 : : } 46 : : 47 : : void 48 : 2823 : 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 : : Dsec elapsed, estimated{}; 68 : : 69 : : Assert( it > 0, "it == 0" ); 70 : : 71 : : tk::real eps = std::numeric_limits< real >::epsilon(); 72 : : 73 : : // Compute time difference between start and now in seconds 74 : 2823 : elapsed = clock::now() - m_start; 75 : : 76 [ + + ]: 2823 : if (rest > eps) { 77 : : 78 [ + + ][ + - ]: 141 : if (res0 > eps && res > eps) { 79 : : // Estimate time until convergence to steady state (assume log-lin fn) 80 : : using std::log; 81 : 133 : auto d = log(res0/res); 82 [ + - ]: 133 : Dsec recent_elapsed = clock::now() - m_prev; 83 [ + - ]: 133 : Dsec est_res = std::abs(d) > eps ? 84 : 133 : recent_elapsed * log(res/rest) / d : 85 : : Dsec(0); 86 : : 87 : : // Ignore negative estimates (temporarily non-decreasing residual) 88 : 133 : estimated = std::max( Dsec(0), est_res ); 89 : 133 : m_prev = clock::now(); 90 : : } 91 : : 92 : : 93 : : } else { 94 : : 95 : : // Estimate time until nstep in seconds (assume lin-lin fn) 96 [ + - ]: 2682 : Dsec est_nstep = elapsed * static_cast<tk::real>(nstep-it) / it; 97 : : // Estimate time until term in seconds (assume lin-lin fn) 98 : : tk::real large = std::numeric_limits< real >::max() - 1; 99 [ + - ][ + + ]: 2682 : Dsec est_term = std::abs(time) > eps && term < large ? 100 : 731 : elapsed * (term-time) / time : 101 : 2682 : est_nstep; 102 : : 103 : : // Time stepping will stop at term or nstep, whichever is sooner 104 : 2682 : estimated = std::min( est_term, est_nstep ); 105 : : } 106 : : 107 : : // Put elapsed time in watch as hours:minutes:seconds 108 : 2823 : elapsedWatch.hrs = duration_cast< hours >( elapsed ); 109 : 2823 : elapsedWatch.min = duration_cast< minutes >( elapsed ) % hours(1); 110 : 2823 : elapsedWatch.sec = duration_cast< seconds >( elapsed ) % minutes(1); 111 : : // Put estimated time in watch as hours:minutes:seconds 112 : 2823 : estimatedWatch.hrs = duration_cast< hours >( estimated ); 113 : 2823 : estimatedWatch.min = duration_cast< minutes >( estimated ) % hours(1); 114 : 2823 : estimatedWatch.sec = duration_cast< seconds >( estimated ) % minutes(1); 115 : 2823 : } 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 : : const auto d = Timer::Dsec( stamp ); 127 : : return 128 : : Timer::Watch( duration_cast< Timer::hours >( d ), 129 : : duration_cast< Timer::minutes >( d ) % Timer::hours(1), 130 : 83 : duration_cast< Timer::seconds >( d ) % Timer::minutes(1) ); 131 : : }