1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
// *****************************************************************************
/*!
  \file      src/Main/WalkerPrint.hpp
  \copyright 2012-2015 J. Bakosi,
             2016-2018 Los Alamos National Security, LLC.,
             2019-2020 Triad National Security, LLC.
             All rights reserved. See the LICENSE file for details.
  \brief     Walker-specific pretty printer functionality
  \details   Walker-specific pretty printer functionality.
*/
// *****************************************************************************
#ifndef WalkerPrint_h
#define WalkerPrint_h

#include <functional>
#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <utility>
#include <cstddef>

#include <brigand/algorithms/for_each.hpp>

#include "NoWarning/format.hpp"

#include "Keywords.hpp"
#include "Print.hpp"
#include "Types.hpp"
#include "Tags.hpp"
#include "RNGPrint.hpp"
#include "ContainerUtil.hpp"
#include "Walker/Options/DiffEq.hpp"
#include "Walker/Options/InitPolicy.hpp"
#include "Walker/Options/CoeffPolicy.hpp"
#include "Walker/InputDeck/InputDeck.hpp"

namespace tk { namespace ctr { struct Term; } }

namespace walker {

extern ctr::InputDeck g_inputdeck_defaults;
extern ctr::InputDeck g_inputdeck;

//! WalkerPrint : tk::RNGPrint
class WalkerPrint : public tk::RNGPrint {

  public:
    //! Constructor
    //! \param[in] screen Screen output filename
    //! \param[in,out] str Verbose stream
    //! \param[in] mode Open mode for screen output file, see
    //!   http://en.cppreference.com/w/cpp/io/ios_base/openmode
    //! \param[in,out] qstr Quiet stream
    //! \see tk::RNGPrint::RNGPrint and tk::Print::Print
    explicit WalkerPrint( const std::string& screen,
                          std::ostream& str = std::clog,
                          std::ios_base::openmode mode = std::ios_base::out,
                          std::ostream& qstr = std::cout ) :
      RNGPrint( screen, str, mode, qstr ) {}

    //! Print section only if differs from its default
    template< typename Option, typename... tags >
    void Section() const {
      if (g_inputdeck.get< tags... >() !=<--- Syntax Error: AST broken, binary operator '!=' doesn't have two operands.
            g_inputdeck_defaults.get< tags... >() ) {
        Option opt;
        auto& group = opt.group();
        auto& value = opt.name( g_inputdeck.get< tags... >() );
        m_stream << m_section_title_value_fmt % m_section_indent
                                              % m_section_bullet
                                              % group
                                              % value;
        m_stream << m_section_underline_fmt
                    % m_section_indent
                    % std::string( m_section_indent.size() + 3 +
                                   group.size() + value.size(), '-' );
      }
    }

    //! Print item: 'name : value' only if differs from its default
    //! \param[in] name Name of item
    template< typename... tags >
    void Item( const std::string& name ) const {
      if (g_inputdeck.get< tags... >() !=
            g_inputdeck_defaults.get< tags... >() )
        m_stream << m_item_name_value_fmt
                    % m_item_indent % name % g_inputdeck.get<tags...>();
    }

    //! Print control option: 'group : option' only if differs from its default
    template<typename Option, typename... tags>
    void Item() const {
      if (g_inputdeck.get< tags... >() !=
            g_inputdeck_defaults.get< tags... >() ) {
        Option opt;
        m_stream << m_item_name_value_fmt
                    % m_item_indent % opt.group()
                    % opt.name( g_inputdeck.get< tags... >() );
      }
    }

    // Helper class for compact output of diff eq policies
    class Policies {
      public:
        // Default constructor
        explicit Policies() : init(), coef() {}
        // Initializer constructor
        explicit Policies( const std::string& i, const std::string& c ) :
          init(i), coef(c) {}
        // Operator += for adding up two Policies structs
        Policies& operator+= ( const Policies& p ) {
          init += p.init;
          coef += p.coef;
          return *this;
        }
        // Output unique policies to output stream
        friend std::ostream& operator<< ( std::ostream& os, const Policies& p )
        {
          Policies copy( p );     // copy policies
          copy.unique();          // get rid of duplicate policies
          os << "i:" << copy.init << ", c:" << copy.coef;
          return os;
        }

      private:
        // Make all policies unique
        void unique() {
          tk::unique( init );
          tk::unique( coef );
        }

        std::string init;
        std::string coef;
    };

    //! Print equation list with policies
    //! \param[in] t Section title
    //! \param[in] factory Factory to get equation data from
    //! \param[in] ntypes Unique equation types
    template< class Factory >
    void eqlist( const std::string& t,
                 const Factory& factory,
                 std::size_t ntypes ) const
    {
      if (!factory.empty()) {
        section( t );
        item( "Unique equation types", ntypes );
        item( "With all policy combinations", factory.size() );
        raw( '\n' );
        raw( m_item_indent + "Legend: equation name : supported policies\n" );
        raw( '\n' );
        raw( m_item_indent + "Policy codes:\n" );
        static_assert( tk::HasTypedef_code_v< kw::init::info >,
                       "Policy code undefined for keyword" );
        static_assert( tk::HasTypedef_code_v< kw::coeff::info >,
                       "Policy code undefined for keyword" );
        raw( m_item_indent + " * " + *kw::init::code() + ": "
                           + kw::init::name() + ":\n" );
        brigand::for_each< ctr::InitPolicy::keywords >( echoPolicies(this) );
        raw( m_item_indent + " * " + *kw::coeff::code() + ": "
                           + kw::coeff::name() + ":\n" );
        brigand::for_each< ctr::CoeffPolicy::keywords >( echoPolicies(this) );
        raw( '\n' );
        // extract eqname and supported policies
        const auto ip = ctr::InitPolicy();
        const auto cp = ctr::CoeffPolicy();
        std::map< std::string, Policies > eqs;      // eqname : policies
        for (const auto& f : factory)
          eqs[ DiffEqName( f.first ) ] +=
            Policies( ip.code( f.first.template get< tag::initpolicy >() ),
                      cp.code( f.first.template get< tag::coeffpolicy >() ) );
        // output eqname and supported policies
        for (const auto& e : eqs)
          m_stream << m_item_name_value_fmt % m_item_indent
                                            % e.first % e.second;
      }
    }

    //! Print time integration header
    void inthead( const std::string& t, const std::string& name,
                  const std::string& legend, const std::string& head ) const;

    //! Print statistics and PDFs
    void statistics( const std::string& t ) const;

    //! Print configuration of a stack of differential equations
    void diffeqs( const std::string& t,
      const std::vector< std::vector< std::pair< std::string, std::string > > >&
        info ) const;

  private:
    //! Return differential equation name
    //! \param[in] key Equation key
    //! \return Differential equation name based on key
    template< class Key >
    std::string DiffEqName ( const Key& key ) const
    { return ctr::DiffEq().name( key.template get< tag::diffeq >() ); }

    //! Echo statistics container contents if differs from default
    void stats( const std::string& msg ) const;

    //! Echo pdfs container contents if differs from default applying op
    void pdfs( const std::string& msg,
               std::function<
                 std::ostream& ( std::ostream&,
                                 const std::vector< tk::ctr::Term >&,
                                 const std::vector< tk::real >&,
                                 const std::string&,
                                 const std::vector< tk::real >& ) > op ) const;
};

} // walker::

#endif // WalkerPrint_h