Branch data Line data Source code
1 : : // *****************************************************************************
2 : : /*!
3 : : \file src/Main/Inciter.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 Inciter, computational shock hydrodynamics tool, Charm++ main
10 : : chare.
11 : : \details Inciter, computational shock hydrodynamics tool, Charm++ main
12 : : chare. This file contains the definition of the Charm++ main chare,
13 : : equivalent to main() in Charm++-land.
14 : : */
15 : : // *****************************************************************************
16 : :
17 : : #include <unordered_map>
18 : : #include <vector>
19 : : #include <iostream>
20 : :
21 : : #include "XystBuildConfig.hpp"
22 : : #ifdef XYST_AMPI
23 : : #include "NoWarning/mpi.hpp"
24 : : #endif
25 : :
26 : : #include "Types.hpp"
27 : : #include "Init.hpp"
28 : : #include "Timer.hpp"
29 : : #include "Exception.hpp"
30 : : #include "ProcessException.hpp"
31 : : #include "InciterConfig.hpp"
32 : : #include "LBSwitch.hpp"
33 : :
34 : : #include "NoWarning/inciter.decl.h"
35 : :
36 : : #if defined(__clang__)
37 : : #pragma clang diagnostic push
38 : : #pragma clang diagnostic ignored "-Wmissing-variable-declarations"
39 : : #endif
40 : :
41 : : //! \brief Charm handle to the main proxy, facilitates call-back to finalize,
42 : : //! etc., must be in global scope, unique per executable
43 : : CProxy_Main mainProxy;
44 : :
45 : : //! Load balancer switch group proxy
46 : : tk::CProxy_LBSwitch LBSwitchProxy;
47 : :
48 : : #if defined(__clang__)
49 : : #pragma clang diagnostic pop
50 : : #endif
51 : :
52 : : //! Inciter declarations and definitions
53 : : namespace inciter {
54 : :
55 : : //! Global-scope data. Initialized by the main chare and distibuted to all PEs
56 : : //! by the Charm++ runtime system. Though semantically not const, all these
57 : : //! global data should be considered read-only. See also
58 : : //! http://charm.cs.illinois.edu/manuals/html/charm++/manual.html. The data
59 : : //! below is global-scope because they must be available to all PEs which could
60 : : //! be on different machines.
61 : :
62 : : #if defined(__clang__)
63 : : #pragma clang diagnostic push
64 : : #pragma clang diagnostic ignored "-Wmissing-variable-declarations"
65 : : #endif
66 : :
67 : : //! Configuration data structure, containing all input data
68 : : //! \details This object is in global scope, it contains all of user input, and
69 : : //! thus it is made available to all PEs for convenience reasons. The runtime
70 : : //! system distributes it to all PEs during initialization. Once distributed,
71 : : //! the object does not change.
72 : : ctr::Config g_cfg;
73 : :
74 : : //! Number of times restarted counter
75 : : int g_nrestart;
76 : :
77 : : #if defined(__clang__)
78 : : #pragma clang diagnostic pop
79 : : #endif
80 : :
81 : : } // inciter::
82 : :
83 : : #ifdef XYST_AMPI
84 : : //! Main function for Charm++'s AMPI
85 : : //! \note If this is not defined, Charm++ does not wait for CkExit().
86 : : int main( int, char** ) {
87 : : MPI_Init( nullptr, nullptr );
88 : : return 0;
89 : : }
90 : : #endif
91 : :
92 : : //! \brief Charm++ main chare for the shock hydrodynamics executable, inciter.
93 : : //! \details In inciter the Charm++ runtime system is initialized only after the
94 : : //! mesh has been read in, partitioned, and the necessary data structures,
95 : : //! e.g., communication maps, have been generated. This delayed initialization
96 : : //! of the Charm++ runtime system is required since the mesh partitioning is
97 : : //! done by Zoltan, an MPI library. Note that this Charm++ main chare object
98 : : //! should not be in a namespace.
99 : : class Main : public CBase_Main {
100 : :
101 : : public:
102 : : //! \brief Constructor
103 : : //! \details Inciter's main chare constructor is the entry point of the
104 : : //! Charm++ portion of inciter, called by the Charm++ runtime system. The
105 : : //! constructor does basic initialization steps, prints out some useful
106 : : //! information to screen (in verbose mode), and instantiates a driver.
107 : : //! Since Charm++ is fully asynchronous, the constructor usually spawns
108 : : //! asynchronous objects and immediately exits. Thus in the body of the
109 : : //! main chare constructor we fire up an 'execute' chare, which then calls
110 : : //! back to Main::execute(). Finishing the main chare constructor the
111 : : //! Charm++ runtime system then starts the network-migration of all
112 : : //! global-scope data (if any). The execute chare calling back to
113 : : //! Main::execute() signals the end of the migration of the global-scope
114 : : //! data. Then we are ready to execute the driver. Since inciter is
115 : : //! parallel and asynchronous, its driver fires up additional Charm++
116 : : //! chare objects which then call back to Main::finalize() at some point
117 : : //! in the future when all work has been finished. finalize() then exits
118 : : //! by calling Charm++'s CkExit(), shutting down the runtime system.
119 : : //! \see http://charm.cs.illinois.edu/manuals/html/charm++/manual.html
120 : 246 : explicit Main( CkArgMsg* msg )
121 : 246 : try :
122 [ + - ][ + - ]: 246 : m_timer(1)
123 : : {
124 [ + - ]: 246 : tk::setSignalHandlers();
125 : : using inciter::g_cfg;
126 : : // Parse command line
127 [ + - ]: 246 : g_cfg.cmdline( msg->argc, msg->argv );
128 [ + - ]: 243 : tk::echoHeader( tk::HeaderType::INCITER );
129 [ + - ][ + - ]: 243 : tk::echoBuildEnv( msg->argv[0] );
130 [ + - ]: 243 : tk::echoRunEnv(msg->argc, msg->argv, g_cfg.get< tag::quiescence >());
131 [ + - ][ + - ]: 243 : delete msg;
132 [ + - ]: 243 : mainProxy = thisProxy;
133 [ + + ]: 243 : if (g_cfg.get< tag::quiescence >()) {
134 [ + - ][ + - ]: 174 : CkStartQD( CkCallback( CkIndex_Main::quiescence(), thisProxy ) );
[ + - ]
135 : : }
136 [ + - ]: 243 : m_timer.emplace_back();
137 : : // Parse control file
138 [ + - ]: 243 : inciter::g_cfg.control();
139 : : // Fire up an asynchronous execute object, which when created at some
140 : : // future point in time will call back to this->execute(). This is
141 : : // necessary so that this->execute() can access already migrated
142 : : // global-scope data.
143 [ + - ]: 243 : CProxy_execute::ckNew();
144 [ - - ]: 243 : } catch (...) { tk::processExceptionCharm(); }
145 : :
146 : : //! Migrate constructor: returning from a checkpoint
147 : 10 : explicit Main( CkMigrateMessage* msg )
148 : 10 : try :
149 [ + - ][ + - ]: 10 : CBase_Main( msg ), m_timer(1)
150 : : {
151 [ - + ]: 10 : if (CkMyPe() != 0) return;
152 [ + - ]: 10 : tk::setSignalHandlers();
153 : : using inciter::g_cfg;
154 : : // Parse command line after restart
155 : 10 : g_cfg.cmdline( reinterpret_cast<CkArgMsg*>(msg)->argc,
156 [ + - ]: 10 : reinterpret_cast<CkArgMsg*>(msg)->argv );
157 [ + - ]: 10 : tk::echoHeader( tk::HeaderType::INCITER );
158 [ + - ][ + - ]: 10 : tk::echoBuildEnv( reinterpret_cast<CkArgMsg*>(msg)->argv[0] );
159 : 10 : tk::echoRunEnv( reinterpret_cast<CkArgMsg*>(msg)->argc,
160 : 10 : reinterpret_cast<CkArgMsg*>(msg)->argv,
161 [ + - ]: 10 : g_cfg.get< tag::quiescence >() );
162 : : // increase number of restarts (available for Transporter on PE 0)
163 : 10 : ++inciter::g_nrestart;
164 [ + - ]: 10 : mainProxy = thisProxy;
165 [ + - ]: 10 : if (g_cfg.get< tag::quiescence >()) {
166 [ + - ][ + - ]: 10 : CkStartQD( CkCallback( CkIndex_Main::quiescence(), thisProxy ) );
[ + - ]
167 : : }
168 [ + - ]: 10 : m_timer.emplace_back();
169 : : // Parse control file after restart
170 [ + - ]: 10 : g_cfg.control();
171 [ - - ]: 0 : } catch (...) { tk::processExceptionCharm(); }
172 : :
173 : : //! Execute driver created and initialized by constructor
174 : 243 : void execute() {
175 : : try {
176 [ + - ][ + - ]: 243 : m_timestamp.emplace_back("Migrate global-scope data", m_timer[1].hms());
177 : : // Instantiate Transporter chare on PE 0 which drives time-integration
178 [ + - ]: 243 : inciter::CProxy_Transporter::ckNew( 0 );
179 [ - - ]: 0 : } catch (...) { tk::processExceptionCharm(); }
180 : 243 : }
181 : :
182 : : //! Towards normal exit but collect chare state first (if any)
183 : 252 : void finalize() {
184 : 252 : tk::finalize( m_timer, m_timestamp );
185 : 0 : }
186 : :
187 : : //! Entry method triggered when quiescence is detected
188 [ - - ][ - - ]: 0 : [[noreturn]] void quiescence() { Throw( "Quiescence detected" ); }
[ - - ]
189 : :
190 : : /** @name Charm++ pack/unpack serializer member functions */
191 : : ///@{
192 : : //! \brief Pack/Unpack serialize member function
193 : : //! \param[in,out] p Charm++'s PUP::er serializer object reference
194 : : //! \note This is a Charm++ mainchare, pup() is thus only for
195 : : //! checkpoint/restart.
196 : 154 : void pup( PUP::er &p ) override {
197 : 154 : p | m_timer;
198 : 154 : }
199 : : //! \brief Pack/Unpack serialize operator|
200 : : //! \param[in,out] p Charm++'s PUP::er serializer object reference
201 : : //! \param[in,out] m Mainchare object reference
202 : : friend void operator|( PUP::er& p, Main& m ) { m.pup(p); }
203 : : //@}
204 : :
205 : : private:
206 : : std::vector< tk::Timer > m_timer; //!< Timers
207 : : //! Time stamps in h:m:s with labels
208 : : std::vector< std::pair< std::string, tk::Timer::Watch > > m_timestamp;
209 : : };
210 : :
211 : : //! \brief Charm++ chare execute
212 : : //! \details By the time this object is constructed, the Charm++ runtime system
213 : : //! has finished migrating all global-scoped read-only objects which happens
214 : : //! after the main chare constructor has finished.
215 : : class execute : public CBase_execute {
216 : : public:
217 : : //! Constructor
218 [ + - ]: 243 : explicit execute() { mainProxy.execute(); }
219 : : //! Migrate constructor
220 : 10 : explicit execute( CkMigrateMessage* m ) : CBase_execute( m ) {}
221 : : };
222 : :
223 : : #include "NoWarning/inciter.def.h"
|