Walker test code coverage report
Current view: top level - Walker - Distributor.cpp (source / functions) Hit Total Coverage
Commit: test_coverage.info Lines: 224 236 94.9 %
Date: 2022-09-21 13:52:12 Functions: 20 22 90.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 265 534 49.6 %

           Branch data     Line data    Source code
       1                 :            : // *****************************************************************************
       2                 :            : /*!
       3                 :            :   \file      src/Walker/Distributor.cpp
       4                 :            :   \copyright 2012-2015 J. Bakosi,
       5                 :            :              2016-2018 Los Alamos National Security, LLC.,
       6                 :            :              2019-2021 Triad National Security, LLC.
       7                 :            :              All rights reserved. See the LICENSE file for details.
       8                 :            :   \brief     Distributor drives the time integration of differential equations
       9                 :            :   \details   Distributor drives the time integration of differential equations.
      10                 :            :     The implementation uses the Charm++ runtime system and is fully asynchronous,
      11                 :            :     overlapping computation, communication as well as I/O. The algorithm
      12                 :            :     utilizes the structured dagger (SDAG) Charm++ functionality. The high-level
      13                 :            :     overview of the algorithm structure and how it interfaces with Charm++ is
      14                 :            :     discussed in the Charm++ interface file src/Walker/distributor.ci.
      15                 :            : */
      16                 :            : // *****************************************************************************
      17                 :            : 
      18                 :            : #include <list>
      19                 :            : #include <string>
      20                 :            : #include <algorithm>
      21                 :            : #include <functional>
      22                 :            : #include <iomanip>
      23                 :            : #include <iostream>
      24                 :            : #include <iterator>
      25                 :            : #include <limits>
      26                 :            : #include <cmath>
      27                 :            : #include <cstddef>
      28                 :            : 
      29                 :            : #include "NoWarning/format.hpp"
      30                 :            : 
      31                 :            : #include "Macro.hpp"
      32                 :            : #include "Print.hpp"
      33                 :            : #include "Tags.hpp"
      34                 :            : #include "StatCtr.hpp"
      35                 :            : #include "Exception.hpp"
      36                 :            : #include "Particles.hpp"
      37                 :            : #include "LoadDistributor.hpp"
      38                 :            : #include "Distributor.hpp"
      39                 :            : #include "Integrator.hpp"
      40                 :            : #include "DiffEqStack.hpp"
      41                 :            : #include "TxtStatWriter.hpp"
      42                 :            : #include "PDFReducer.hpp"
      43                 :            : #include "PDFWriter.hpp"
      44                 :            : #include "Options/PDFFile.hpp"
      45                 :            : #include "Options/PDFPolicy.hpp"
      46                 :            : #include "Walker/InputDeck/InputDeck.hpp"
      47                 :            : #include "NoWarning/walker.decl.h"
      48                 :            : 
      49                 :            : extern CProxy_Main mainProxy;
      50                 :            : 
      51                 :            : using walker::Distributor;
      52                 :            : 
      53                 :         93 : Distributor::Distributor() :
      54                 :            :   m_output( { false, false } ),
      55                 :            :   m_it( 0 ),
      56                 :            :   m_npar( 0 ),
      57                 :            :   m_t( 0.0 ),
      58         [ +  - ]:         93 :   m_dt( computedt() ),
      59                 :            :   m_intproxy(),
      60                 :            :   m_timer(),
      61 [ +  - ][ -  - ]:         93 :   m_nameOrdinary( g_inputdeck.momentNames( tk::ctr::ordinary ) ),
      62                 :         93 :   m_nameCentral( g_inputdeck.momentNames( tk::ctr::central ) ),
      63         [ +  - ]:         93 :   m_ordinary( m_nameOrdinary.size(), 0.0 ),
      64 [ +  - ][ -  - ]:         93 :   m_central( m_nameCentral.size(), 0.0 ),
      65                 :            :   m_ordupdf(),
      66                 :            :   m_ordbpdf(),
      67                 :            :   m_ordtpdf(),
      68                 :            :   m_cenupdf(),
      69                 :            :   m_cenbpdf(),
      70                 :            :   m_centpdf(),
      71                 :            :   m_tables(),
      72 [ +  - ][ +  - ]:        279 :   m_moments()
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
      73                 :            : // *****************************************************************************
      74                 :            : // Constructor
      75                 :            : // *****************************************************************************
      76                 :            : {
      77                 :            :   // Get command line object reference
      78                 :            :   const auto& cmd = g_inputdeck.get< tag::cmd >();
      79                 :            : 
      80                 :            :   // Compute load distribution given total work (= number of particles) and
      81                 :            :   // user-specified virtualization
      82         [ +  - ]:         93 :   uint64_t chunksize = 0, remainder = 0;
      83         [ +  - ]:         93 :   auto nchare = tk::linearLoadDistributor(
      84                 :            :                   cmd.get< tag::virtualization >(),
      85                 :            :                   g_inputdeck.get< tag::discr, tag::npar >(),
      86                 :            :                   CkNumPes(),
      87                 :            :                   chunksize,
      88                 :            :                   remainder );
      89                 :            :   Assert( chunksize != 0, "Chunksize must not be zero" );
      90                 :            : 
      91                 :            :   // Compute total number of particles distributed over all workers. Note that
      92                 :            :   // this number will not necessarily be the same as given by the user, coming
      93                 :            :   // from g_inputdeck.get< tag::discr, tag::npar >(), since each Charm++ chare
      94                 :            :   // array element constructor takes this chunksize argument, which equals the
      95                 :            :   // number of particles the array element (worker) will work on.
      96                 :         93 :   m_npar = static_cast< tk::real >( nchare * chunksize );
      97                 :            : 
      98         [ +  - ]:         93 :   auto print = printer();
      99                 :            : 
     100                 :            :   // Print out info on what will be done and how
     101         [ +  - ]:         93 :   info( print, chunksize, nchare );
     102                 :            : 
     103                 :            :   // Output header for statistics output file
     104 [ +  + ][ -  + ]:         93 :   tk::TxtStatWriter sw( !m_nameOrdinary.empty() || !m_nameCentral.empty() ?
     105                 :            :                         cmd.get< tag::io, tag::stat >() :
     106                 :            :                         std::string(),
     107                 :            :                         g_inputdeck.get< tag::flformat, tag::stat >(),
     108 [ +  + ][ +  - ]:        186 :                         g_inputdeck.get< tag::prec, tag::stat >() );
     109         [ +  - ]:         93 :   sw.header( m_nameOrdinary, m_nameCentral, m_tables.first );
     110                 :            : 
     111                 :            :   // Print out time integration header
     112                 :            :   print.endsubsection();
     113 [ +  - ][ +  - ]:        186 :   print.diag( "Starting time stepping ..." );
                 [ +  - ]
     114         [ +  - ]:         93 :   header( print );
     115                 :            : 
     116                 :            :   // Start timer measuring total integration time
     117         [ +  - ]:         93 :   m_timer.emplace_back();
     118                 :            : 
     119                 :            :   // Construct and initialize map of statistical moments
     120         [ +  + ]:       1434 :   for (const auto& product : g_inputdeck.get< tag::stat >())
     121         [ +  - ]:       1341 :     m_moments[ product ] = 0.0;
     122                 :            : 
     123                 :            :   // Activate SDAG-wait for estimation of ordinary statistics
     124         [ +  - ]:         93 :   thisProxy.wait4ord();
     125                 :            :   // Activate SDAG-wait for estimation of PDFs at select times
     126         [ +  - ]:         93 :   thisProxy.wait4pdf();
     127                 :            : 
     128                 :            :   // Create statistics merger chare group collecting chare contributions
     129         [ +  - ]:         93 :   CProxy_Collector collproxy = CProxy_Collector::ckNew( thisProxy );
     130                 :            : 
     131                 :            :   // Create partcle writer Charm++ chare nodegroup
     132                 :            :   tk::CProxy_ParticleWriter particlewriter =
     133         [ +  - ]:         93 :     tk::CProxy_ParticleWriter::ckNew( cmd.get< tag::io, tag::particles >() );
     134                 :            : 
     135                 :            :   // Fire up asynchronous differential equation integrators
     136                 :            :   m_intproxy =
     137                 :         93 :     CProxy_Integrator::ckNew( thisProxy, collproxy, particlewriter, chunksize,
     138 [ +  - ][ -  + ]:        186 :                               static_cast<int>( nchare ) );
                 [ -  - ]
     139                 :         93 : }
     140                 :            : 
     141                 :            : void
     142                 :         93 : Distributor::info( const WalkerPrint& print,
     143                 :            :                    uint64_t chunksize,
     144                 :            :                    std::size_t nchare )
     145                 :            : // *****************************************************************************
     146                 :            : //  Print information at startup
     147                 :            : //! \param[in] print Pretty printer object to use for printing
     148                 :            : //! \param[in] chunksize Chunk size, see Base/LoadDistribution.h
     149                 :            : //! \param[in] nchare Total number of Charem++ Integrator chares doing work
     150                 :            : // *****************************************************************************
     151                 :            : {
     152                 :            :   // Get command line object reference
     153                 :            :   const auto& cmd = g_inputdeck.get< tag::cmd >();
     154                 :            : 
     155         [ +  - ]:        186 :   print.part( "Factory" );
     156                 :            : 
     157                 :            :   // Print out info data layout
     158         [ +  - ]:         93 :   print.list( "Particle properties data layout (CMake: PARTICLE_DATA_LAYOUT)",
     159 [ +  - ][ +  - ]:        279 :               std::list< std::string >{ tk::Particles::layout() } );
         [ +  + ][ -  + ]
         [ -  - ][ -  - ]
     160                 :            : 
     161                 :            :   // Re-create differential equations stack for output
     162                 :         93 :   DiffEqStack stack;
     163                 :            : 
     164                 :            :   // Print out information on factory
     165         [ +  - ]:         93 :   print.eqlist( "Registered differential equations",
     166 [ +  - ][ +  - ]:        186 :                 stack.factory(), stack.ntypes() );
     167                 :            :   print.endpart();
     168                 :            : 
     169                 :            :   // Instantiate tables to sample and output to statistics file
     170         [ +  - ]:         93 :   m_tables = stack.tables();
     171                 :            : 
     172                 :            :   // Print out information on problem
     173 [ +  - ][ +  - ]:        186 :   print.part( "Problem" );
                 [ +  - ]
     174                 :            : 
     175                 :            :   // Print out info on problem title
     176         [ +  - ]:         93 :   if ( !g_inputdeck.get< tag::title >().empty() )
     177         [ +  - ]:         93 :     print.title( g_inputdeck.get< tag::title >() );
     178                 :            : 
     179                 :            :   // Print out info on settings of selected differential equations
     180 [ +  - ][ +  - ]:        186 :   print.diffeqs( "Differential equations integrated", stack.info() );
                 [ +  - ]
     181                 :            : 
     182                 :            :   // Print out info on RNGs selected
     183                 :            :   // ...
     184                 :            : 
     185                 :            :   // Print I/O filenames
     186 [ +  - ][ +  - ]:        186 :   print.section( "Output filenames" );
                 [ +  + ]
     187         [ +  + ]:         93 :   if (!g_inputdeck.get< tag::stat >().empty())
     188 [ +  - ][ +  - ]:        180 :     print.item( "Statistics", cmd.get< tag::io, tag::stat >() );
     189         [ +  + ]:         93 :   if (!g_inputdeck.get< tag::pdf >().empty())
     190 [ +  - ][ +  - ]:         32 :     print.item( "PDF", cmd.get< tag::io, tag::pdf >() );
     191         [ +  + ]:         93 :   if (!g_inputdeck.get< tag::param, tag::position, tag::depvar >().empty())
     192 [ +  - ][ +  - ]:         12 :     print.item( "Particle positions", cmd.get< tag::io, tag::particles >() );
     193                 :            : 
     194                 :            :   // Print discretization parameters
     195 [ +  - ][ +  - ]:        186 :   print.section( "Discretization parameters" );
                 [ +  - ]
     196         [ +  - ]:         93 :   print.item( "Number of time steps",
     197 [ +  - ][ +  - ]:        186 :               g_inputdeck.get< tag::discr, tag::nstep >() );
     198         [ +  - ]:         93 :   print.item( "Terminate time",
     199 [ +  - ][ +  - ]:        186 :               g_inputdeck.get< tag::discr, tag::term >() );
     200         [ +  - ]:         93 :   print.item( "Initial time step size",
     201 [ +  - ][ +  - ]:        186 :               g_inputdeck.get< tag::discr, tag::dt >() );
     202                 :            : 
     203                 :            :   // Print output intervals
     204 [ +  - ][ +  - ]:        186 :   print.section( "Output intervals" );
                 [ +  - ]
     205                 :            :   const auto& interval = g_inputdeck.get< tag::output, tag::iter >();
     206 [ +  - ][ +  - ]:        186 :   print.item( "TTY", interval.get< tag::tty >() );
                 [ +  + ]
     207         [ +  + ]:         93 :   if (!g_inputdeck.get< tag::stat >().empty())
     208 [ +  - ][ +  - ]:        180 :     print.item( "Statistics", interval.get< tag::stat >() );
     209         [ +  + ]:         93 :   if (!g_inputdeck.get< tag::pdf >().empty())
     210 [ +  - ][ +  - ]:         32 :     print.item( "PDF", interval.get< tag::pdf >() );
     211         [ +  + ]:         93 :   if (!g_inputdeck.get< tag::param, tag::position, tag::depvar >().empty())
     212 [ +  - ][ +  - ]:         12 :     print.item( "Particles", interval.get< tag::particles >() );
     213                 :            : 
     214                 :            :   // Print out statistics estimated
     215 [ +  - ][ +  - ]:        186 :   print.statistics( "Statistical moments and distributions" );
                 [ +  - ]
     216                 :            : 
     217                 :            :   // Print out info on load distirubtion
     218 [ +  - ][ +  - ]:        186 :   print.section( "Load distribution" );
                 [ +  - ]
     219         [ +  - ]:         93 :   print.item( "Virtualization [0.0...1.0]",
     220 [ +  - ][ +  - ]:        186 :               g_inputdeck.get< tag::cmd, tag::virtualization >() );
     221 [ +  - ][ +  - ]:        186 :   print.item( "Number of work units", nchare );
                 [ +  - ]
     222         [ +  - ]:         93 :   print.item( "User load (# of particles)",
     223 [ +  - ][ +  - ]:        186 :               g_inputdeck.get< tag::discr, tag::npar >() );
     224 [ +  - ][ +  - ]:        186 :   print.item( "Chunksize (load per work unit)", chunksize );
                 [ +  - ]
     225         [ +  - ]:         93 :   print.item( "Actual load (# of particles)",
     226 [ +  - ][ -  + ]:        186 :               std::to_string( nchare * chunksize ) +
         [ -  + ][ -  - ]
                 [ -  - ]
     227 [ +  - ][ -  + ]:        186 :               " (=" +
                 [ -  - ]
     228 [ +  - ][ +  - ]:        372 :               std::to_string( nchare ) + "*" +
         [ +  - ][ -  + ]
         [ -  + ][ -  + ]
         [ -  - ][ -  - ]
                 [ -  - ]
     229 [ +  - ][ +  - ]:        394 :               std::to_string( chunksize ) + ")" );
         [ +  - ][ +  - ]
         [ +  + ][ -  + ]
         [ -  - ][ -  - ]
     230                 :         93 : }
     231                 :            : 
     232                 :            : tk::real
     233                 :     520624 : Distributor::computedt()
     234                 :            : // *****************************************************************************
     235                 :            : // Compute size of next time step
     236                 :            : //! \return Size of dt for the next time step
     237                 :            : // *****************************************************************************
     238                 :            : {
     239                 :            :   // Simply return a constant user-defined dt for now
     240                 :     520624 :   return g_inputdeck.get< tag::discr, tag::dt >();
     241                 :            : }
     242                 :            : 
     243                 :            : void
     244                 :     520531 : Distributor::estimateOrd( tk::real* ord, [[maybe_unused]] int n )
     245                 :            : // *****************************************************************************
     246                 :            : // Estimate ordinary moments
     247                 :            : //! \param[in] ord Ordinary moments (sum) collected over all chares
     248                 :            : //! \param[in] n Number of ordinary moments in array ord
     249                 :            : // *****************************************************************************
     250                 :            : {
     251                 :            :   Assert( static_cast<std::size_t>(n) == m_ordinary.size(),
     252                 :            :           "Number of ordinary moments contributed not equal to expected" );
     253                 :            : 
     254                 :            :   // Add contribution from PE to total sums, i.e., u[i] += v[i] for all i
     255         [ +  + ]:    3003634 :   for (std::size_t i=0; i<m_ordinary.size(); ++i) m_ordinary[i] += ord[i];
     256                 :            : 
     257                 :            :   // Finish computing moments, i.e., divide sums by the number of samples
     258                 :            :   // cppcheck-suppress useStlAlgorithm
     259         [ +  + ]:    3003634 :   for (auto& m : m_ordinary) m /= m_npar;
     260                 :            : 
     261                 :            :   // Activate SDAG trigger signaling that ordinary moments have been estimated
     262                 :     520531 :   estimateOrdDone();
     263                 :     520531 : }
     264                 :            : 
     265                 :            : void
     266                 :     520531 : Distributor::estimateCen( tk::real* cen, [[maybe_unused]] int n )
     267                 :            : // *****************************************************************************
     268                 :            : // Estimate ordinary moments
     269                 :            : //! \param[in] cen Central moments (sum) collected over all chares
     270                 :            : //! \param[in] n Number of central moments in array cen
     271                 :            : // *****************************************************************************
     272                 :            : {
     273                 :            :   Assert( static_cast<std::size_t>(n) == m_central.size(),
     274                 :            :           "Number of central moments contributed not equal to expected" );
     275                 :            : 
     276                 :            :   // Add contribution from PE to total sums, i.e., u[i] += v[i] for all i
     277         [ +  + ]:    5309645 :   for (std::size_t i=0; i<m_central.size(); ++i) m_central[i] += cen[i];
     278                 :            : 
     279                 :            :   // Finish computing moments, i.e., divide sums by the number of samples
     280                 :            :   // cppcheck-suppress useStlAlgorithm
     281         [ +  + ]:    5309645 :   for (auto& m : m_central) m /= m_npar;
     282                 :            : 
     283                 :            :   // Activate SDAG trigger signaling that central moments have been estimated
     284                 :     520531 :   estimateCenDone();
     285                 :     520531 : }
     286                 :            : 
     287                 :            : void
     288         [ +  - ]:     520531 : Distributor::estimateOrdPDF( CkReductionMsg* msg )
     289                 :            : // *****************************************************************************
     290                 :            : // Estimate ordinary PDFs
     291                 :            : //! \param[in] msg Serialized vectors of uni-, bi-, and tri-variate PDFs
     292                 :            : // *****************************************************************************
     293                 :            : {
     294                 :            :   // Deserialize final PDFs
     295                 :            :   PUP::fromMem creator( msg->getData() );
     296         [ +  - ]:     520531 :   creator | m_ordupdf;
     297         [ +  - ]:     520531 :   creator | m_ordbpdf;
     298         [ +  - ]:     520531 :   creator | m_ordtpdf;
     299                 :            : 
     300                 :            :   delete msg;
     301                 :            : 
     302                 :            :   // Activate SDAG trigger signaling that ordinary PDFs have been estimated
     303         [ +  - ]:     520531 :   estimateOrdPDFDone();
     304                 :     520531 : }
     305                 :            : 
     306                 :            : void
     307         [ +  - ]:     520531 : Distributor::estimateCenPDF( CkReductionMsg* msg )
     308                 :            : // *****************************************************************************
     309                 :            : // Estimate central PDFs
     310                 :            : //! \param[in] msg Serialized vectors of uni-, bi-, and tri-variate PDFs
     311                 :            : // *****************************************************************************
     312                 :            : {
     313                 :            :   // Deserialize final PDFs
     314                 :            :   PUP::fromMem creator( msg->getData() );
     315         [ +  - ]:     520531 :   creator | m_cenupdf;
     316         [ +  - ]:     520531 :   creator | m_cenbpdf;
     317         [ +  - ]:     520531 :   creator | m_centpdf;
     318                 :            : 
     319                 :            :   delete msg;
     320                 :            : 
     321                 :            :   // Activate SDAG trigger signaling that central PDFs have been estimated
     322         [ +  - ]:     520531 :   estimateCenPDFDone();
     323                 :     520531 : }
     324                 :            : 
     325                 :            : void
     326                 :     520531 : Distributor::outStat()
     327                 :            : // *****************************************************************************
     328                 :            : // Output statistics to file
     329                 :            : // *****************************************************************************
     330                 :            : {
     331                 :            :   // lambda to sample tables to write to statistics file
     332                 :     398499 :   auto extra = [this]() -> std::vector< tk::real > {
     333                 :     398499 :     std::vector< tk::real > x( m_tables.second.size() );
     334                 :            :     std::size_t j = 0;
     335         [ +  + ]:     398599 :     for (const auto& t : m_tables.second) x[ j++ ] = tk::sample<1>(m_t,t)[0];
     336                 :     398499 :     return x;
     337                 :     520531 :   };
     338                 :            : 
     339                 :            :   // Append statistics file at selected times
     340         [ +  + ]:     520531 :   if (!((m_it+1) % g_inputdeck.get< tag::output, tag::iter, tag::stat >())) {
     341 [ +  + ][ -  + ]:     398499 :     tk::TxtStatWriter sw( !m_nameOrdinary.empty() || !m_nameCentral.empty() ?
     342                 :            :                           g_inputdeck.get< tag::cmd, tag::io, tag::stat >() :
     343                 :            :                           std::string(),
     344                 :            :                           g_inputdeck.get< tag::flformat, tag::stat >(),
     345                 :            :                           g_inputdeck.get< tag::prec, tag::stat >(),
     346 [ +  + ][ +  - ]:     796998 :                           std::ios_base::app );
     347 [ +  - ][ +  - ]:     796998 :     if (sw.stat( m_it, m_t, m_ordinary, m_central, extra() ))
                 [ +  + ]
     348                 :     368496 :       m_output.get< tag::stat >() = true;
     349                 :            :   }
     350                 :     520531 : }
     351                 :            : 
     352                 :            : void
     353                 :     520531 : Distributor::outPDF()
     354                 :            : // *****************************************************************************
     355                 :            : // Output PDFs to file
     356                 :            : // *****************************************************************************
     357                 :            : {
     358                 :     520531 :   const auto term = g_inputdeck.get< tag::discr, tag::term >();
     359                 :            :   const auto eps = std::numeric_limits< tk::real >::epsilon();
     360                 :     520531 :   const auto nstep = g_inputdeck.get< tag::discr, tag::nstep >();
     361                 :     520531 :   const auto pdffreq = g_inputdeck.get< tag::output, tag::iter, tag::pdf >();
     362                 :            : 
     363                 :            :   // output PDFs at t=0 (regardless of whether it was requested), or at
     364                 :            :   // selected times, or in the last time step (regardless of whether it was
     365                 :            :   // requested
     366         [ +  + ]:     520531 :   if ( m_it == 0 ||
     367         [ +  + ]:     520438 :        !((m_it+1) % pdffreq) ||
     368 [ +  - ][ +  + ]:      63383 :        (std::fabs(m_t+m_dt-term) < eps || (m_it+1) >= nstep) )
     369                 :            :   {
     370                 :            :     // Generate iteration count and physical time for PDF output. In the first
     371                 :            :     // iteration, the particles are NOT advanced, see Integration::advance(),
     372                 :            :     // and we write it=0 and time=0.0 into the PDF files. For the rest of the
     373                 :            :     // iterations we write the iteration count and the physical time
     374                 :            :     // corresponding to the iteration just completed.
     375         [ +  + ]:     457154 :     auto it = m_it == 0 ? m_it : m_it + 1;
     376         [ +  + ]:     457154 :     auto t = m_it == 0 ? m_t : m_t + m_dt;
     377                 :            : 
     378                 :     457154 :     outUniPDF( it, t );                 // Output univariate PDFs to file(s)
     379                 :     457154 :     outBiPDF( it, t );                  // Output bivariate PDFs to file(s)
     380                 :     457154 :     outTriPDF( it, t );                 // Output trivariate PDFs to file(s)
     381                 :     457154 :     m_output.get< tag::pdf >() = true;  // Signal that PDFs were written
     382                 :            :   }
     383                 :     520531 : }
     384                 :            : 
     385                 :            : void
     386                 :         34 : Distributor::writeUniPDF( std::uint64_t it,
     387                 :            :                           tk::real t,
     388                 :            :                           const tk::UniPDF& p,
     389                 :            :                           tk::ctr::Moment m,
     390                 :            :                           std::size_t idx )
     391                 :            : // *****************************************************************************
     392                 :            : // Write univariate PDF to file
     393                 :            : //! \param[in] it Iteration count to write in output file
     394                 :            : //! \param[in] t Physical time to write in output file
     395                 :            : //! \param[in] p Univariate PDF to output
     396                 :            : //! \param[in] m ORDINARY or CENTRAL PDF we are writing
     397                 :            : //! \param[in] idx Index of the PDF of all ordinary or central PDFs requested
     398                 :            : // *****************************************************************************
     399                 :            : {
     400                 :            :   // Get PDF metadata
     401                 :            :   const auto nfo =
     402                 :            :     tk::ctr::pdfInfo< 1 >( g_inputdeck.get< tag::discr, tag::binsize >(),
     403                 :            :                            g_inputdeck.get< tag::cmd, tag::io, tag::pdfnames >(),
     404                 :            :                            g_inputdeck.get< tag::discr, tag::extent >(),
     405                 :            :                            g_inputdeck.get< tag::pdf >(),
     406                 :            :                            m,
     407                 :            :                            idx,
     408                 :            :                            it,
     409                 :         34 :                            t );
     410                 :            : 
     411                 :            :   // Construct PDF file name: base name + '_' + pdf name
     412                 :            :   std::string filename =
     413 [ +  - ][ +  - ]:         34 :     g_inputdeck.get< tag::cmd, tag::io, tag::pdf >() + '_' + nfo.name;
     414                 :            : 
     415                 :            :   // Augment PDF filename by time stamp if PDF output file policy is multiple
     416         [ -  + ]:         34 :   if (g_inputdeck.get< tag::selected, tag::pdfpolicy >() ==
     417                 :            :       tk::ctr::PDFPolicyType::MULTIPLE)
     418 [ -  - ][ -  - ]:          0 :     filename += '_' + std::to_string( m_t );
         [ -  - ][ -  - ]
                 [ -  - ]
     419                 :            : 
     420                 :            :   // Augment PDF filename by '.txt' extension
     421                 :            :   filename += ".txt";
     422                 :            : 
     423                 :            :   // Create new PDF file (overwrite if exists)
     424                 :            :   tk::PDFWriter pdfw( filename,
     425                 :            :                       g_inputdeck.get< tag::flformat, tag::pdf >(),
     426         [ +  - ]:         34 :                       g_inputdeck.get< tag::prec, tag::pdf >() );
     427                 :            : 
     428                 :            :   // Output PDF
     429         [ +  - ]:         34 :   pdfw.writeTxt( p, nfo );
     430                 :         34 : }
     431                 :            : 
     432                 :            : void
     433                 :         12 : Distributor::writeBiPDF( std::uint64_t it,
     434                 :            :                          tk::real t,
     435                 :            :                          const tk::BiPDF& p,
     436                 :            :                          tk::ctr::Moment m,
     437                 :            :                          std::size_t idx )
     438                 :            : // *****************************************************************************
     439                 :            : // Write bivariate PDF to file
     440                 :            : //! \param[in] it Iteration count to write in output file
     441                 :            : //! \param[in] t Physical time to write in output file
     442                 :            : //! \param[in] p Bivariate PDF to output
     443                 :            : //! \param[in] m ORDINARY or CENTRAL PDF we are writing
     444                 :            : //! \param[in] idx Index of the PDF of all ordinary or central PDFs requested
     445                 :            : // *****************************************************************************
     446                 :            : {
     447                 :            :   // Get PDF metadata
     448                 :            :   const auto nfo =
     449                 :            :     tk::ctr::pdfInfo< 2 >( g_inputdeck.get< tag::discr, tag::binsize >(),
     450                 :            :                            g_inputdeck.get< tag::cmd, tag::io, tag::pdfnames >(),
     451                 :            :                            g_inputdeck.get< tag::discr, tag::extent >(),
     452                 :            :                            g_inputdeck.get< tag::pdf >(),
     453                 :            :                            m,
     454                 :            :                            idx,
     455                 :            :                            it,
     456                 :         12 :                            t );
     457                 :            : 
     458                 :            :   // Construct PDF file name: base name + '_' + pdf name
     459                 :            :   std::string filename =
     460 [ +  - ][ +  - ]:         12 :     g_inputdeck.get< tag::cmd, tag::io, tag::pdf >() + '_' + nfo.name;
     461                 :            : 
     462                 :            :   // Augment PDF filename by time stamp if PDF output file policy is multiple
     463         [ -  + ]:         12 :   if (g_inputdeck.get< tag::selected, tag::pdfpolicy >() ==
     464                 :            :       tk::ctr::PDFPolicyType::MULTIPLE)
     465 [ -  - ][ -  - ]:          0 :     filename += '_' + std::to_string( m_t );
         [ -  - ][ -  - ]
                 [ -  - ]
     466                 :            : 
     467                 :            :   const auto& filetype = g_inputdeck.get< tag::selected, tag::filetype >();
     468                 :            : 
     469                 :            :   // Augment PDF filename by the appropriate extension
     470         [ +  + ]:         12 :   if (filetype == tk::ctr::PDFFileType::TXT)
     471                 :            :     filename += ".txt";
     472         [ -  + ]:          2 :   else if (filetype == tk::ctr::PDFFileType::GMSHTXT ||
     473                 :            :            filetype == tk::ctr::PDFFileType::GMSHBIN )
     474                 :            :     filename += ".gmsh";
     475         [ +  - ]:          2 :   else if (filetype == tk::ctr::PDFFileType::EXODUSII)
     476                 :            :     filename += ".exo";
     477 [ -  - ][ -  - ]:          0 :   else Throw( "Unkown PDF file type attempting to output bivariate PDF" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     478                 :            : 
     479                 :            :   // Create new PDF file (overwrite if exists)
     480                 :            :   tk::PDFWriter pdfw( filename,
     481                 :            :                       g_inputdeck.get< tag::flformat, tag::pdf >(),
     482         [ +  - ]:         12 :                       g_inputdeck.get< tag::prec, tag::pdf >() );
     483                 :            : 
     484                 :            :   // Output PDF
     485         [ +  + ]:         12 :   if (filetype == tk::ctr::PDFFileType::TXT)
     486         [ +  - ]:         10 :     pdfw.writeTxt( p, nfo );
     487         [ -  + ]:          2 :   else if (filetype == tk::ctr::PDFFileType::GMSHTXT)
     488         [ -  - ]:          0 :     pdfw.writeGmshTxt( p, nfo,
     489                 :            :                        g_inputdeck.get< tag::selected, tag::pdfctr >() );
     490         [ -  + ]:          2 :   else if (filetype == tk::ctr::PDFFileType::GMSHBIN)
     491         [ -  - ]:          0 :     pdfw.writeGmshBin( p, nfo,
     492                 :            :                        g_inputdeck.get< tag::selected, tag::pdfctr >() );
     493         [ +  - ]:          2 :   else if (filetype == tk::ctr::PDFFileType::EXODUSII)
     494         [ +  - ]:          2 :     pdfw.writeExodusII( p, nfo,
     495                 :            :                         g_inputdeck.get< tag::selected, tag::pdfctr >() );
     496                 :         12 : }
     497                 :            : 
     498                 :            : void
     499                 :         12 : Distributor::writeTriPDF( std::uint64_t it,
     500                 :            :                           tk::real t,
     501                 :            :                           const tk::TriPDF& p,
     502                 :            :                           tk::ctr::Moment m,
     503                 :            :                           std::size_t idx )
     504                 :            : // *****************************************************************************
     505                 :            : // Write trivariate PDF to file
     506                 :            : //! \param[in] it Iteration count to write in output file
     507                 :            : //! \param[in] t Physical time to write in output file
     508                 :            : //! \param[in] p Trivariate PDF to output
     509                 :            : //! \param[in] m ORDINARY or CENTRAL PDF we are writing
     510                 :            : //! \param[in] idx Index of the PDF of all ordinary or central PDFs requested
     511                 :            : // *****************************************************************************
     512                 :            : {
     513                 :            :   // Get PDF metadata
     514                 :            :   const auto nfo =
     515                 :            :     tk::ctr::pdfInfo< 3 >( g_inputdeck.get< tag::discr, tag::binsize >(),
     516                 :            :                            g_inputdeck.get< tag::cmd, tag::io, tag::pdfnames >(),
     517                 :            :                            g_inputdeck.get< tag::discr, tag::extent >(),
     518                 :            :                            g_inputdeck.get< tag::pdf >(),
     519                 :            :                            m,
     520                 :            :                            idx,
     521                 :            :                            it,
     522                 :         12 :                            t );
     523                 :            : 
     524                 :            :   // Construct PDF file name: base name + '_' + pdf name
     525                 :            :   std::string filename =
     526 [ +  - ][ +  - ]:         12 :     g_inputdeck.get< tag::cmd, tag::io, tag::pdf >() + '_' + nfo.name;
     527                 :            : 
     528                 :            :   // Augment PDF filename by time stamp if PDF output file policy is multiple
     529         [ -  + ]:         12 :   if (g_inputdeck.get< tag::selected, tag::pdfpolicy >() ==
     530                 :            :       tk::ctr::PDFPolicyType::MULTIPLE)
     531 [ -  - ][ -  - ]:          0 :     filename += '_' + std::to_string( m_t );
         [ -  - ][ -  - ]
                 [ -  - ]
     532                 :            : 
     533                 :            :   const auto& filetype = g_inputdeck.get< tag::selected, tag::filetype >();
     534                 :            : 
     535                 :            :   // Augment PDF filename by the appropriate extension
     536         [ +  + ]:         12 :   if (filetype == tk::ctr::PDFFileType::TXT)
     537                 :            :     filename += ".txt";
     538         [ -  + ]:          4 :   else if (filetype == tk::ctr::PDFFileType::GMSHTXT ||
     539                 :            :            filetype == tk::ctr::PDFFileType::GMSHBIN )
     540                 :            :     filename += ".gmsh";
     541         [ +  - ]:          4 :   else if (filetype == tk::ctr::PDFFileType::EXODUSII)
     542                 :            :     filename += ".exo";
     543 [ -  - ][ -  - ]:          0 :   else Throw( "Unkown PDF file type attempting to output trivariate PDF" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     544                 :            : 
     545                 :            :   // Create new PDF file (overwrite if exists)
     546                 :            :   tk::PDFWriter pdfw( filename,
     547                 :            :                       g_inputdeck.get< tag::flformat, tag::pdf >(),
     548         [ +  - ]:         12 :                       g_inputdeck.get< tag::prec, tag::pdf >() );
     549                 :            : 
     550                 :            :   // Output PDF
     551         [ +  + ]:         12 :   if (filetype == tk::ctr::PDFFileType::TXT)
     552         [ +  - ]:          8 :     pdfw.writeTxt( p, nfo );
     553         [ -  + ]:          4 :   else if (filetype == tk::ctr::PDFFileType::GMSHTXT)
     554         [ -  - ]:          0 :      pdfw.writeGmshTxt( p, nfo,
     555                 :            :                         g_inputdeck.get< tag::selected, tag::pdfctr >() );
     556         [ -  + ]:          4 :   else if (filetype == tk::ctr::PDFFileType::GMSHBIN)
     557         [ -  - ]:          0 :      pdfw.writeGmshBin( p, nfo,
     558                 :            :                         g_inputdeck.get< tag::selected, tag::pdfctr >() );
     559         [ +  - ]:          4 :   else if (filetype == tk::ctr::PDFFileType::EXODUSII)
     560         [ +  - ]:          4 :     pdfw.writeExodusII( p, nfo,
     561                 :            :                         g_inputdeck.get< tag::selected, tag::pdfctr >() );
     562                 :         12 : }
     563                 :            : 
     564                 :            : void
     565                 :     457154 : Distributor::outUniPDF( std::uint64_t it, tk::real t )
     566                 :            : // *****************************************************************************
     567                 :            : // Output all requested univariate PDFs to file(s)
     568                 :            : //! \param[in] it Iteration count to write in output file
     569                 :            : //! \param[in] t Physical time to write in output file
     570                 :            : // *****************************************************************************
     571                 :            : {
     572                 :            :   std::size_t idx = 0;
     573         [ +  + ]:     457178 :   for (const auto& p : m_ordupdf)
     574                 :         24 :     writeUniPDF( it, t, p, tk::ctr::Moment::ORDINARY, idx++ );
     575                 :            :   idx = 0;
     576         [ +  + ]:     457164 :   for (const auto& p : m_cenupdf)
     577                 :         10 :     writeUniPDF( it, t, p, tk::ctr::Moment::CENTRAL, idx++ );
     578                 :     457154 : }
     579                 :            : 
     580                 :            : void
     581                 :     457154 : Distributor::outBiPDF( std::uint64_t it, tk::real t )
     582                 :            : // *****************************************************************************
     583                 :            : // Output all requested bivariate PDFs to file(s)
     584                 :            : //! \param[in] it Iteration count to write in output file
     585                 :            : //! \param[in] t Physical time to write in output file
     586                 :            : //! \return Number of PDFs written
     587                 :            : // *****************************************************************************
     588                 :            : {
     589                 :            :   std::size_t idx = 0;
     590         [ +  + ]:     457160 :   for (const auto& p : m_ordbpdf)
     591                 :          6 :     writeBiPDF( it, t, p, tk::ctr::Moment::ORDINARY, idx++ );
     592                 :            :   idx = 0;
     593         [ +  + ]:     457160 :   for (const auto& p : m_cenbpdf) {
     594                 :          6 :     writeBiPDF( it, t, p, tk::ctr::Moment::CENTRAL, idx++ );
     595                 :            :   }
     596                 :     457154 : }
     597                 :            : 
     598                 :            : void
     599                 :     457154 : Distributor::outTriPDF( std::uint64_t it, tk::real t )
     600                 :            : // *****************************************************************************
     601                 :            : // Output all requested trivariate PDFs to file(s)
     602                 :            : //! \param[in] it Iteration count to write in output file
     603                 :            : //! \param[in] t Physical time to write in output file
     604                 :            : //! \return Number of PDFs written
     605                 :            : // *****************************************************************************
     606                 :            : {
     607                 :            :   std::size_t idx = 0;
     608         [ +  + ]:     457160 :   for (const auto& p : m_ordtpdf) {
     609                 :          6 :     writeTriPDF( it, t, p, tk::ctr::Moment::ORDINARY, idx++ );
     610                 :            :   }
     611                 :            :   idx = 0;
     612         [ +  + ]:     457160 :   for (const auto& p : m_centpdf) {
     613                 :          6 :     writeTriPDF( it, t, p, tk::ctr::Moment::CENTRAL, idx++ );
     614                 :            :   }
     615                 :     457154 : }
     616                 :            : 
     617                 :            : void
     618                 :     520531 : Distributor::evaluateTime()
     619                 :            : // *****************************************************************************
     620                 :            : // Evaluate time step, compute new time step size, decide if it is time to quit
     621                 :            : // *****************************************************************************
     622                 :            : {
     623                 :     520531 :   const auto term = g_inputdeck.get< tag::discr, tag::term >();
     624                 :            :   const auto eps = std::numeric_limits< tk::real >::epsilon();
     625                 :     520531 :   const auto nstep = g_inputdeck.get< tag::discr, tag::nstep >();
     626                 :            : 
     627                 :            :   // Increase number of iterations taken
     628                 :     520531 :   ++m_it;
     629                 :            :   // Advance physical time
     630                 :     520531 :   m_t += m_dt;
     631                 :            :   // Truncate the size of last time step
     632         [ +  + ]:     520531 :   if (m_t > term) m_t = term;
     633                 :            :   // Compute size of next time step
     634                 :     520531 :   m_dt = computedt();
     635                 :            :   // Echo one-liner info on time step
     636                 :     520531 :   report();
     637                 :            : 
     638                 :            :   // Finish if either max iterations or max time reached 
     639 [ +  + ][ +  + ]:     520531 :   if ( std::fabs(m_t-term) > eps && m_it < nstep ) {
     640                 :            : 
     641                 :            :     if (g_inputdeck.stat()) {
     642                 :            :       // Update map of statistical moments
     643                 :            :       std::size_t ord = 0;
     644                 :            :       std::size_t cen = 0;
     645         [ +  + ]:    7791314 :       for (const auto& product : g_inputdeck.get< tag::stat >())
     646         [ +  + ]:    7270876 :         if (tk::ctr::ordinary( product ))
     647                 :    2482549 :           m_moments[ product ] = m_ordinary[ ord++ ];
     648                 :            :         else
     649                 :    4788327 :           m_moments[ product ] = m_central[ cen++ ];
     650                 :            : 
     651                 :            :       // Zero statistics counters and accumulators
     652                 :            :       std::fill( begin(m_ordinary), end(m_ordinary), 0.0 );
     653                 :            :       std::fill( begin(m_central), end(m_central), 0.0 );
     654                 :            : 
     655                 :            :       // Re-activate SDAG-wait for estimation of ordinary stats for next step
     656                 :     520438 :       thisProxy.wait4ord();
     657                 :            :       // Re-activate SDAG-wait for estimation of PDFs for next step
     658                 :     520438 :       thisProxy.wait4pdf();
     659                 :            :     }
     660                 :            : 
     661                 :            :     // Continue with next time step with all integrators
     662                 :     520438 :     m_intproxy.advance( m_dt, m_t, m_it, m_moments );
     663                 :            : 
     664                 :         93 :   } else finish();
     665                 :     520531 : }
     666                 :            : 
     667                 :            : void
     668                 :         93 : Distributor::finish()
     669                 :            : // *****************************************************************************
     670                 :            : // Normal finish of time stepping
     671                 :            : // *****************************************************************************
     672                 :            : {
     673                 :            :   // Print out reason for stopping
     674                 :         93 :   const auto term = g_inputdeck.get< tag::discr, tag::term >();
     675                 :         93 :   const auto nstep = g_inputdeck.get< tag::discr, tag::nstep >();
     676                 :            : 
     677                 :         93 :   auto print = printer();
     678                 :            : 
     679                 :            :   print.endsubsection();
     680         [ +  + ]:         93 :   if (m_it >= g_inputdeck.get< tag::discr, tag::nstep >())
     681 [ +  - ][ -  + ]:         18 :      print.note( "Normal finish, maximum number of iterations reached: " +
                 [ -  - ]
     682 [ +  - ][ +  - ]:         18 :                  std::to_string( nstep ) );
     683                 :            :    else 
     684 [ +  - ][ -  + ]:        168 :      print.note( "Normal finish, maximum time reached: " +
                 [ -  - ]
     685         [ +  - ]:        168 :                  std::to_string( term ) );
     686                 :            : 
     687                 :            :   // Quit
     688         [ +  - ]:         93 :   mainProxy.finalize();
     689                 :         93 : }
     690                 :            : 
     691                 :            : void
     692                 :          0 : Distributor::nostat()
     693                 :            : // *****************************************************************************
     694                 :            : //  Charm++ reduction target enabling shortcutting sync points if no stats
     695                 :            : //! \details This reduction target is called if there are no statistics nor PDFs
     696                 :            : //!   to be estimated and thus some synchronization points can be skipped. Upon
     697                 :            : //!   this call we simply finish up the time step as usual.
     698                 :            : // *****************************************************************************
     699                 :            : {
     700                 :          0 :   evaluateTime();
     701                 :          0 : }
     702                 :            : 
     703                 :            : void
     704                 :         93 : Distributor::header( const WalkerPrint& print ) const
     705                 :            : // *****************************************************************************
     706                 :            : // Print out time integration header
     707                 :            : //! \param[in] print Pretty printer object to use for printing
     708                 :            : // *****************************************************************************
     709                 :            : {
     710         [ +  - ]:         93 :   print.inthead( "Time integration", "Differential equations testbed",
     711                 :            :     "Legend: it - iteration count\n"
     712                 :            :     "         t - time\n"
     713                 :            :     "        dt - time step size\n"
     714                 :            :     "       ETE - estimated time elapsed (h:m:s)\n"
     715                 :            :     "       ETA - estimated time for accomplishment (h:m:s)\n"
     716                 :            :     "       out - status flags, legend:\n"
     717                 :            :     "             s - statistics output\n"
     718                 :            :     "             p - PDFs output\n"
     719                 :            :     "             x - particle positions output\n",
     720                 :            :     "\n      it             t            dt        ETE        ETA   out\n"
     721 [ +  - ][ +  - ]:        465 :       " ---------------------------------------------------------------\n" );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     722                 :         93 : }
     723                 :            : 
     724                 :            : void
     725                 :     520531 : Distributor::report()
     726                 :            : // *****************************************************************************
     727                 :            : // Print out one-liner report on time step
     728                 :            : // *****************************************************************************
     729                 :            : {
     730         [ +  + ]:     520531 :   if (!(m_it % g_inputdeck.get< tag::output, tag::iter, tag::tty >())) {
     731                 :            : 
     732                 :            :   const auto parfreq =
     733                 :       1699 :     g_inputdeck.get< tag::output, tag::iter, tag::particles >();
     734                 :            :   const auto poseq =
     735                 :            :     !g_inputdeck.get< tag::param, tag::position, tag::depvar >().empty();
     736                 :            : 
     737                 :            :     // estimated time elapsed and for accomplishment
     738                 :            :     tk::Timer::Watch ete, eta;
     739                 :       1699 :     m_timer[0].eta( g_inputdeck.get< tag::discr, tag::term >(), m_t,
     740                 :            :                     g_inputdeck.get< tag::discr, tag::nstep >(), m_it,
     741                 :            :                     ete, eta );
     742                 :            : 
     743                 :       1699 :     auto print = printer();
     744                 :            : 
     745                 :            :     // Output one-liner
     746                 :            :     print << std::setfill(' ') << std::setw(8) << m_it << "  "
     747                 :            :           << std::scientific << std::setprecision(6)
     748                 :            :           << std::setw(12) << m_t << "  "
     749                 :            :           << m_dt << "  "
     750                 :            :           << std::setfill('0')
     751                 :            :           << std::setw(3) << ete.hrs.count() << ":"
     752                 :            :           << std::setw(2) << ete.min.count() << ":"
     753                 :            :           << std::setw(2) << ete.sec.count() << "  "
     754                 :            :           << std::setw(3) << eta.hrs.count() << ":"
     755                 :            :           << std::setw(2) << eta.min.count() << ":"
     756                 :            :           << std::setw(2) << eta.sec.count() << "  ";
     757                 :            : 
     758                 :            :     // Augment one-liner with output indicators
     759         [ +  + ]:       1699 :     if (m_output.get< tag::stat >()) print << 's';
     760         [ +  + ]:       1699 :     if (m_output.get< tag::pdf >()) print << 'p';
     761 [ +  + ][ -  + ]:       1699 :     if (poseq && !(m_it % parfreq)) print << 'x';
     762                 :            : 
     763                 :            :     // Reset output indicators
     764                 :       1699 :     m_output.get< tag::stat >() = false;
     765         [ +  - ]:       1699 :     m_output.get< tag::pdf >() = false;
     766                 :            : 
     767                 :            :     print << std::endl;
     768                 :            :   }
     769                 :     520531 : }
     770                 :            : 
     771                 :            : #include "NoWarning/distributor.def.h"

Generated by: LCOV version 1.14