1 /* _______________________________________________________________________
2
3 DAKOTA: Design Analysis Kit for Optimization and Terascale Applications
4 Copyright 2014-2020 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
5 This software is distributed under the GNU Lesser General Public License.
6 For more information, see the README file in the top Dakota directory.
7 _______________________________________________________________________ */
8
9 //- Class: global_defs
10 //- Description: Global object initializations and global function
11 //- implementations
12 //- Owner: Mike Eldred
13
14 #include <system_error>
15 #include <boost/math/constants/constants.hpp>
16 #include "dakota_global_defs.hpp"
17 #include "ParamResponsePair.hpp"
18 #include "PRPMultiIndex.hpp"
19 #include "DakotaGraphics.hpp"
20 #include "DakotaInterface.hpp"
21 #include "ParallelLibrary.hpp"
22 #include "ProblemDescDB.hpp"
23 #include "ResultsManager.hpp"
24 #include "EvaluationStore.hpp"
25
26 // Toggle for MPI debug hold
27 //#define MPI_DEBUG
28
29 #if defined(MPI_DEBUG) && defined(MPICH_NAME)
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #endif
35
36
37 static const char rcsId[]="@(#) $Id: dakota_global_defs.cpp 6716 2010-04-03 18:35:08Z wjbohnh $";
38
39
40 namespace Dakota {
41
42 // --------------------------
43 // Instantiate global objects
44 // --------------------------
45
46 double PI = boost::math::constants::pi<double>();
47 double HALF_LOG_2PI = std::log(2.0*PI)/2.0;
48
49 /// by default Dakota exits or calls MPI_Abort on errors
50 short abort_mode = ABORT_EXITS;
51
52 std::ostream* dakota_cout = &std::cout; ///< DAKOTA stdout initially points to
53 ///< std::cout, but may be redirected to a tagged ofstream if there are
54 ///< concurrent iterators.
55 std::ostream* dakota_cerr = &std::cerr; ///< DAKOTA stderr initially points to
56 ///< std::cerr, but may be redirected to a tagged ofstream if there are
57 ///< concurrent iterators.
58 PRPCache data_pairs; ///< contains all parameter/response pairs.
59
60 /// Global results database for iterator results
61 ResultsManager iterator_results_db;
62 /// Global database for evaluation storage
63 EvaluationStore evaluation_store_db;
64
65
66 int write_precision = 10; ///< used in ostream data output functions
67 ///< (restart_util.cpp overrides default value)
68
69 MPIManager dummy_mpi_mgr; ///< dummy MPIManager for ref initialization
70 ProgramOptions dummy_prg_opt; ///< dummy ProgramOptions for ref initialization
71 OutputManager dummy_out_mgr; ///< dummy OutputManager for ref initialization
72 ParallelLibrary dummy_lib; ///< dummy ParallelLibrary for ref initialization
73 ProblemDescDB dummy_db; ///< dummy ProblemDescDB for ref initialization
74
75 #ifdef DAKOTA_MODELCENTER
76 int mc_ptr_int = 0; ///< global pointer for ModelCenter API
77 int dc_ptr_int = 0; ///< global pointer for ModelCenter eval DB
78 #endif // DAKOTA_MODELCENTER
79
80 ProblemDescDB *Dak_pddb; ///< set by ProblemDescDB, for use in parsing
81
82
83 // -----------------------
84 // Define global functions
85 // -----------------------
abort_handler(int code)86 void abort_handler(int code)
87 {
88 // WEH - uncomment this code if you want signals to generate a corefile.
89 // This is handy for debugging infinite loops ... which can be
90 // difficult to debug within GDB.
91 //abort();
92
93 // BMA TODO: Do we want to maintain this?
94 // BMA NOTE: If so, on Unix, could use strsignal() to get a friendly name.
95 if (code > 1) // code = 2 (Cntl-C signal), 0 (normal), & -1/1 (abnormal)
96 Cout << "\nDakota caught signal " << code << std::endl;
97
98 // Clean up
99 Cout << std::flush; // flush cout or ofstream redirection
100 Cerr << std::flush; // flush cerr or ofstream redirection
101 iterator_results_db.close(); // flush output files/databases
102
103 if (Dak_pddb) {
104 // cleanup parameters/results files
105 InterfaceList &ifaces = Dak_pddb->interface_list();
106 for (InterfaceList::iterator It = ifaces.begin(); It != ifaces.end(); ++It)
107 It->file_cleanup(); // virtual fn defined for ProcessApplicInterface
108 // properly terminate in parallel
109 Dak_pddb->parallel_library().abort_helper(code);
110 }
111 else {
112 abort_throw_or_exit(code);
113 }
114 }
115
116
117 /** Throw a system_error or call std::exit, with (256 +
118 dakota_code), where dakota_code < 0
119
120 RATIONALE:
121 * Avoid common "standard" exit codes and signals (signum.h) as
122 well as uncaught signals / uncatchable SIGKILL which return 128
123 + <signum> on Linux = [129, 192]
124
125 * Return a value in [0,255] since some operating systems only
126 return the 8 least significant bits, leaves [193, 255] for
127 Dakota. This should make return codes consistent
128 cross-platform. */
abort_throw_or_exit(int dakota_code)129 void abort_throw_or_exit(int dakota_code)
130 {
131 int os_code = 256 + dakota_code;
132 if (abort_mode == ABORT_THROWS) {
133 // throw an error that inherits from std::runtime_error and embeds
134 // the error code
135 std::error_code ecode(os_code, std::generic_category());
136 throw(std::system_error(ecode, "Dakota aborted"));
137 }
138 else
139 std::exit(os_code); // or std::exit(EXIT_FAILURE) from /usr/include/stdlib.h
140 }
141
142
143 /// Tie various signal handlers to Dakota's abort_handler function
register_signal_handlers()144 void register_signal_handlers()
145 {
146 #if defined(__MINGW32__) || defined(_MSC_VER)
147 std::signal(SIGBREAK, Dakota::abort_handler);
148 #else
149 // BMA: SIGKILL can't be caught; consider removing:
150 std::signal(SIGKILL, Dakota::abort_handler);
151 #endif
152 std::signal(SIGTERM, Dakota::abort_handler);
153 std::signal(SIGINT, Dakota::abort_handler);
154 }
155
156
157 /** See details in code for details, depending on MPI implementation in use. */
mpi_debug_hold()158 void mpi_debug_hold()
159 {
160 #ifdef MPI_DEBUG
161 // hold parallel job prior to MPI_Init() in order to attach debugger to
162 // master process. Then step past ParallelLibrary instantiation and attach
163 // debugger to other processes.
164 //#ifdef MPICH2
165 #ifdef MPICH_NAME
166 // To use this approach, set $DAKOTA_DEBUGPIPE to a suitable name,
167 // and create $DAKOTA_DEBUGPIPE by executing "mkfifo $DAKOTA_DEBUGPIPE".
168 // After invoking "mpirun ... dakota ...", find the processes, invoke
169 // a debugger on them, set breakpoints, and execute "echo >$DAKOTA_DEBUGPIPE"
170 // to write something to $DAKOTA_DEBUGPIPE, thus releasing dakota from
171 // a wait at the open invocation below.
172 char *pname; int dfd;
173 if ( ( pname = getenv("DAKOTA_DEBUGPIPE") ) &&
174 ( dfd = open(pname,O_RDONLY) ) > 0 ) {
175 char buf[80];
176 read(dfd,buf,sizeof(buf));
177 close(dfd);
178 }
179 #else
180 // This simple scheme has been observed to fail with MPICH2
181 int test;
182 std::cin >> test;
183 #endif // MPICH2
184 #endif // MPI_DEBUG
185 }
186
187 } // namespace Dakota
188