///
/// \addtogroup stk_util_diag_writer_detail
/// @{
///
/// @brief The diagnostic writer provides features for the runtime selection of diagnostic output of
/// data and objects.
///
/// The runtime diagnostic output selection is achieved utilizing message marking within the source
/// code and selection from the command line or input deck.
///
/// The First,
///
/// by implementing a <b>dump</b> member function and an <b>operator<<</b> free function, the class
/// may be easily dumped using the <b>&lt;&lt;</b> operator.  And, second, by assigning appropriate
/// bit masks, the diagnostic writer allows the diagnostic output to be selectively output by the
/// developer or user at runtime.
///
/// For Example:<BR>
///
/// \code
///     class AnotherClass
///     {
///     public:
///       AnotherClass(int i)
///       {}
///  
///       double hairyCalc(int i) {
///         return sin((double) i);
///       }
///  
///       Writer &dump(Writer &dout) const {
///         if (dout.shouldPrint()) {
///           dout << "AnotherClass " << push << dendl;
///  
///           dout.m(LOG_MEMBERS) << "m_m1, " << m_m1 << dendl;
///           dout.m(LOG_MEMBERS) << "m_mem2, " << m_mem2 << dendl;
///  
///           if (dout.shouldPrint(LOG_MEMBERS)) {
///             dout << "hairyCalc" << push << dendl;
///             for (int i = 0; i < 1000; ++i)
///               dout << "hairyCalc(" << i << ") = " << hairyCalc(i) << dendl;
///  
///             dout << pop;
///           }
///           dout << pop;
///         }
///         return dout;
///       }
///  
///     private:
///       int		m_m1;
///       int		m_mem2;
///     };
///  
///     inline Writer &operator<<(Writer &dout, const AnotherClass &another_class) {
///       return another_class.dump(dout);
///     }
///  
///     class ShowWriter
///     {
///       void Func() {
///         sierra::diag_writer dout(std::cout);
///         dout.setPrintMask(LOG_LIGHT | LOG_HEAVY | LOG_MEMBERS);
///  
///         int j = 7;
///  
///         m_anotherClassVector.push_back(AnotherClass(j));
///         m_anotherClassVector.push_back(AnotherClass(j*2));
///         m_anotherClassVector.push_back(AnotherClass(j*2 + 1));
///  
///  
///         dout.m(LOG_LIGHT) << "Light weight diagnostic message, j is " << j << dendl;
///         dout.m(LOG_HEAVY) << "Heavy weight diagnostic message " << m_anotherClassVector << dendl;
///       }
///  
///       Writer &dump(Writer &dout) const {
///         if (dout.shouldPrint()) {
///           dout << "ShowWriter, " << push << dendl;
///  
///           dout.m(LOG_MEMBERS) << "m_anotherClassVector, " << m_anotherClassVector << dendl;
///           dout << pop;
///         }
///  
///         return dout;
///       }
///  
///       std::vector<AnotherClass> m_anotherClassVector;
///     };
///  
///     inline Writer &operator<<(Writer &dout, const ShowWriter &show_diag_writer) {
///       return show_diag_writer.dump(dout);
///     }
/// \endcode
///
///
/// \anchor stk_util_diag_writer_howto_add_to_app
/// \section stk_util_diag_writer_add_to_app Adding diagnostic writer to your application
///
/// Adding a diagnostic writer to your application allows you to leave diagnostic
/// code in your application which is only seen when desired.
///
/// <UL>
/// <LI>Create a <i>App</i>_DiagWriter_fwd.h
///
/// The forward definition file defines the LOG_<i>name</i> bit masks which will be used
/// to select the messages to be written to the diagnostic stream.
///
/// \code
///     #ifndef SIERRA_App_DiagWriter_fwd_h
///     #define SIERRA_App_DiagWriter_fwd_h
///    
///     #include <stk_util/diag/Writer_fwd.hpp>
///    
///     namespace sierra {
///     namespace app {
///    
///     enum {
///       LOG_ALWAYS          = sierra::LOG_ALWAYS,
///       LOG_TRACE           = sierra::LOG_TRACE,
///       LOG_TRACE_STATS     = sierra::LOG_TRACE_STATS,
///       LOG_TRACE_SUB_CALLS = sierra::LOG_TRACE_SUB_CALLS,
///       LOG_MEMBERS         = sierra::LOG_MEMBERS,
///    
///       LOG_NOLOAD          = 0x00000100,
///       LOG_NOEXECUTE       = 0x00000200,
///       LOG_SYNTAX_CHECK    = 0x00000400,
///       LOG_INPUT_CHECK     = 0x00000800,
///       LOG_DUMP_SETUP      = 0x00001000,
///       LOG_DUMP_LOAD       = 0x00002000,
///    
///       LOG_CONTROL         = 0x00003F00,
///    
///       LOG_COMM            = 0x00010000,
///       LOG_CONTACT         = 0x00020000,
///       LOG_GEOMETRY        = 0x00040000,
///       LOG_APP04           = 0x00080000,
///       LOG_MATERIAL        = 0x00100000,
///       LOG_MESH_MOD        = 0x00200000,
///       LOG_PARAMS          = 0x00400000,
///       LOG_PLUGINS         = 0x00800000,
///       LOG_SCONTROL        = 0x01000000,
///       LOG_SEARCH          = 0x02000000,
///       LOG_SOLVER          = 0x04000000,
///       LOG_XFER            = 0x08000000,
///       LOG_FIELD           = 0x10000000,
///       LOG_DIAGNOSTICS     = 0xFFFF0000
///     };
///    
///     } // namespace app
///     } // namespace sierra
///    
///     #endif // SIERRA_App_DiagWriter_fwd_h
/// \endcode
///
/// <LI>Create a <i>App</i>_DiagWriter.h
///
/// The diagnostic writer header file defines the parser for parsing the command line and
/// line commands to produce the mask of bits which the user has selected.  It also
/// implements the sentry which the application uses to bootstrap the diagnostic writer.
///
/// \code
///     #ifndef SIERRA_App_DiagWriter_h
///     #define SIERRA_App_DiagWriter_h
///     
///     #include <stk_util/diag/Writer.hpp>
///     #include <Slib_DiagWriterOStream.h>
///     #include <stk_util/diag/WriterParser.hpp>
///     
///     #include <App_DiagWriter_fwd.h>
///     
///     namespace sierra {
///     namespace app {
///     
///     class DiagWriterParser : public Diag::WriterParser
///     {
///     public:
///       DiagWriterParser();
///     };
///     
///     stk_classic::diag::Writer &theDiagWriter();
///     
///     DiagWriterParser &theDiagWriterParser();
///     
///     #define applog sierra::App::theDiagWriter()
///     } // namespace app
///     } // namespace sierra
///     
///     #endif // SIERRA_Aria_DiagWriter_h
/// \endcode
///
/// <LI>Create a <i>App</i>_DiagWriter.C
///
/// The implementation of the parser constructor adds the command line and line command
/// value used to generate the bit mask.  Any combinations of bit masks can be given a
/// name.  This will simplify specification of commonly grouped options for the user.
///
/// \code
///     #include <stk_util/util/Bootstrap.hpp>
///     
///     #include <stk_util/environment/OutputLog.hpp>
///     #include <stk_util/diag/WriterRegistry.hpp>
///     
///     #include <App_DiagWriter.h>
///     
///     namespace sierra {
///     namespace app {
///     
///     DiagWriterParser &
///     theDiagWriterParser()
///     {
///       /* %TRACE% */  /* %TRACE% */
///       static DiagWriterParser parser;
///     
///       return parser;
///     }
///     
///     stk_classic::diag::Writer &
///     theDiagWriter()
///     {
///       /* %TRACE[NONE]% */  /* %TRACE% */
///       static stk_classic::diag::Writer s_diagWriter(sierra::dwout().rdbuf(), theDiagWriterParser().parse(std::getenv("APPLOG")));
///     
///       return s_diagWriter;
///     }
///     
///     
///     DiagWriterParser::DiagWriterParser()
///         : Diag::WriterParser()
///     {
///       /* %TRACE% */  /* %TRACE% */
///       mask("bc",              (unsigned long) (LOG_BC),              "Display boundary condition information");
///       mask("debug",           (unsigned long) (LOG_DEBUG),           "Display debug diagnostic information");
///       mask("eq",              (unsigned long) (LOG_EQ),              "Display equation information");
///       mask("expression",      (unsigned long) (LOG_EXPRESSION),      "Display expression information");
///       mask("hadapt",          (unsigned long) (LOG_HADAPT),          "Display h_adapt diagnostic information");
///       mask("finite_check",    (unsigned long) (LOG_FINITE_CHECK),    "Display warning messages about any non-finite expression values or sensitivities");
///       mask("nonlinear",       (unsigned long) (LOG_NONLINEAR),       "Diaplay nonlinear solver information");
///       mask("pp",              (unsigned long) (LOG_PP),              "Display postprocessor diagnostic information");
///       mask("sens_check",      (unsigned long) (LOG_SENS_CHECK),      "Display messages generated by expression sensitivity checker");
///       mask("fast_sens_check", (unsigned long) (LOG_FAST_SENS_CHECK), "Display messages generated by sensitivity checker (skipping FAD, element, and kernel expressions)");
///       mask("species",         (unsigned long) (LOG_SPECIES),         "Display species information");
///       mask("transfer",        (unsigned long) (LOG_TRANSFER),        "Display transfer information");
///       mask("plugin",          (unsigned long) (LOG_PLUGIN),          "Display plugin information");
///       mask("chaparral",       (unsigned long) (LOG_CHAPARRAL),       "Display chaparral information");
///       mask("utility",         (unsigned long) (LOG_UTILITY),         "Display equation system utility information");
///       mask("pre_assembly",    (unsigned long) (LOG_PREASSEMBLY),     "Display pre-assembly diagnostic information");
///       mask("expression_dump", (unsigned long) (LOG_EXPRESSION_DUMP), "Display the values for every expression and its sensitivities");
///       mask("calore",          (unsigned long) (LOG_CALORE),          "Display additional calore output (hack)");
///       mask("ccfvm",           (unsigned long) (LOG_CCFVM),           "Display additional ccfvm output (hack)");
///       mask("user-sub",        (unsigned long) (LOG_USER_SUB),        "Print user subroutine execution diagnostics");
///     }
///     
///     namespace {
///     
///     void bootstrap()
///     {
///       Diag::registerWriter("applog", applog, theDiagWriterParser());
///     }
///     
///     stk_classic::Bootstrap x(&bootstrap);
///     
///     } // namespace <empty>
///     
///     } // namespace app
///     } // namespace sierra
/// \endcode
///
/// </UL>
///
///
/// \anchor stk_util_diag_writer_howto_assign_new_log_bits
/// \section stk_util_diag_writer_assign_new_log_bits Adding additional LOG_mask
///
/// Adding a new mask and option name requires only adding the new bit to the
/// enumeration in <i>App</i>_DiagWriter_fwd.h, where 0x<i>mmmmmm00</i> is a previously
/// unusd bit:
///
/// \code
///     #ifndef SIERRA_App_DiagWriter_fwd_h
///     #define SIERRA_App_DiagWriter_fwd_h
///    
///     #include <stk_util/diag/Writer_fwd.hpp>
///    
///     namespace sierra {
///     namespace app {
///    
///     enum {
///       LOG_ALWAYS          = sierra::LOG_ALWAYS,
///       LOG_TRACE           = sierra::LOG_TRACE,
///       LOG_TRACE_STATS     = sierra::LOG_TRACE_STATS,
///       LOG_TRACE_SUB_CALLS = sierra::LOG_TRACE_SUB_CALLS,
///       LOG_MEMBERS         = sierra::LOG_MEMBERS,
///    
///       ...
///       LOG_NEWUNUSEDBIT	= 0x<i>mmmmmm00</i>,
///       ...
///
///     };
///    
///     } // namespace app
///     } // namespace sierra
///    
///     #endif // SIERRA_App_DiagWriter_fwd_h
/// \endcode
///
/// And, adding a <b>mask</b> function call in the parser constructor in the <i>App</i>_DiagWriter.C
/// file.
///
/// \code
///     DiagWriterParser::DiagWriterParser()
///         : Diag::WriterParser()
///     {
///       /* %TRACE% */  /* %TRACE% */
///
///       ...
///       mask("new-bit-name", (Diag::PrintMask) (LOG_NEWUNUSEDBIT), "Some brief description");
///       ...
///     }
/// \endcode
///
///
/// \anchor stk_util_diag_writer_howto_add_dump_to_my_class
/// \section stk_util_diag_writer_add_dump_to_my_class Adding diagnostic output to your classes
///
/// To incorporate the diagnostic writer into a class or application, there are
/// only a few steps to follow.  And, by following these guidelines, the newly created
/// class can fully participate is class data diagnostic output.
///
/// In your class header:
/// <UL>
/// <LI>Include your application's diagnostic writer forward header.
///
/// \code
///     #include <App_DiagWriter_fwd.h>
/// \endcode
///
/// <LI>Declare the dump member function.  If this is a base class, be sure the
/// define this member function as virtual if inheritance may be in play.
///
/// \code
/// Writer &dump(Writer &dout) const;
/// \endcode
///
/// <LI>Define the output insertion operator, operator<< to call your member
/// function.
///
/// \code
///     inline Writer &operator<<(Writer &dout, const MyClass &my_class) {
///       return my_class.dump(dout);
///     }
/// \endcode
/// </UL>
///
/// In your class implementation:
/// <UL>
/// <LI>Include your application's diagnostic writer header.
///
/// \code
///     #include <App_DiagWriter.h>;
/// \endcode
///
/// <LI>Define your MyClass::dump(Writer &dout) const member function.  I
/// suggest using the following as a start:
///
/// \code
///     Writer &
///     MyClass::dump(
///       Writer &		dout) const
///     {
///       if (dout.shouldPrint()) {
///         dout << demangle(typeid(MyClass).name()) << ", " << m_name << push << std::endl;
///         MyParentClass::dump(dout).dendl(); // If there is a base class
///    
///         dout.m(LOG_MEMBERS) << "m_information, " << m_information << std::endl;
///         dout << pop;
///       }
///       return dout;
///     }
/// \endcode
///
/// </UL>
///
///
/// \anchor stk_util_diag_writer_howto_add_dump_to_external_class
/// \section stk_util_diag_writer_add_dump_to_external_class Adding diagnostic output to library classes
///
/// \anchor stk_util_diag_writer_howto_write_messages
/// \section stk_util_diag_writer_write_messages Writing to the appout writer
///
/// There are several functions and manipulators which control the selection and
/// formatting of the diagnostic output.
///
/// <UL>
/// <LI>The print mask and the line mask
///
/// It is the interaction of the print mask and line mask which determines is the data is
/// to be written to the diagnostic stream.  The print mask is set by the user on the
/// command line or in the input deck.  The line mask is set by the developer using the
/// <b>m</b> member function and <b>Diag::setlinemask</b> and <b>Diag::resetlinemask</b>
/// manipulators.
///
/// As each << operator is executed, the print mask and current line mask are bitwise
/// anded together.  If the result of this is non zero, then the line is output.
///
/// <LI>std::endl and Diag::dendl
///
/// Be sure to include std::endl or Diag::dendl at the end of each output line.  The end
/// line functions serve as a mask application terminator.  In other word, the mask
/// specified using the m member function are in effect until the std::endl of Diag::dendl
/// functions are called on the diagnostic stream.  Leaving one out can effect the what is
/// selected to be output.
///
/// <LI>Diag::push and Diag::pop
///
/// The push manipulator pushes the current LineMask onto a stack and the pop manipulator
/// restores the LineMask from the top element of the push stack.
///
/// </UL>
///
/// \anchor stk_util_diag_writer_howto_throw_safe
/// \section stk_util_diag_writer_throw_safe Indentation and exceptions
///
/// When exception occur, the pops put-to the output stream are skipped by the exception catch
/// block.  As a result, the indentation can start to march across the screen.  To correct this
/// behavior, add a ThrowSafe sentry within your try block prior to any push operations.
///
/// \code
/// 	try { // TimeStepError
///       stk_classic::diag::WriterThrowSafe throw_safe_sentry;
/// 
///       appout.m(LOG_TEST) << "Executing run_it() on " << name() << push << dendl;
///       run_it();
///       appout.m(LOG_TEST) << pop;   /// Missed when run_it() throws
///     }
///     catch (std::exception &x) {
///       appout.m(LOG_TEST) << "Exception caught running run_it() on " << name() << dendl;
///     }
/// \endcode
///
/// @}
///

