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: ProcessApplicInterface
10 //- Description: Derived class for the case when analysis code simulators use
11 //- fork\exec\wait to provide the function evaluations
12 //- Owner: Mike Eldred
13 //- Version: $Id: ProcessApplicInterface.hpp 6492 2009-12-19 00:04:28Z briadam $
14
15 #ifndef PROCESS_APPLIC_INTERFACE_H
16 #define PROCESS_APPLIC_INTERFACE_H
17
18 #include "ApplicationInterface.hpp"
19 #ifdef _WIN32
20 typedef intptr_t pid_t;
21 #endif
22
23 #include <boost/tuple/tuple.hpp>
24 #include <boost/filesystem/path.hpp>
25 namespace bfs = boost::filesystem;
26
27 namespace Dakota {
28
29
30 /// Substitute parameters and results file names into driver strings
31 String substitute_params_and_results(const String &driver, const String ¶ms, const String &results);
32
33
34 /// Triplet of filesystem paths: e.g., params, results, workdir
35 typedef boost::tuple<bfs::path, bfs::path, bfs::path> PathTriple;
36
37
38 /// Derived application interface class that spawns a simulation code
39 /// using a separate process and communicates with it through files.
40
41 /** ProcessApplicInterface is subclassed for process handles or file
42 completion testing. */
43
44 class ProcessApplicInterface: public ApplicationInterface
45 {
46 public:
47
48 //
49 //- Heading: Constructors and destructor
50 //
51
52 /// constructor
53 ProcessApplicInterface(const ProblemDescDB& problem_db);
54 /// destructor
55 ~ProcessApplicInterface();
56
57 protected:
58
59 //
60 //- Heading: Virtual function redefinitions
61 //
62
63 void derived_map(const Variables& vars, const ActiveSet& set,
64 Response& response, int fn_eval_id);
65 void derived_map_asynch(const ParamResponsePair& pair);
66
67 void wait_local_evaluations(PRPQueue& prp_queue);
68 void test_local_evaluations(PRPQueue& prp_queue);
69
70 const StringArray& analysis_drivers() const;
71
72 void file_cleanup() const;
73
74 void file_and_workdir_cleanup(const bfs::path ¶ms_path,
75 const bfs::path &results_path,
76 const bfs::path &workdir_path,
77 const String &tag) const;
78
79 /// Remove (potentially autotagged for multiple programs) parameters
80 /// and results files with passed root names
81 void remove_params_results_files(const bfs::path& params_path,
82 const bfs::path& results_path) const;
83
84
85 /// Utility to automatically tag parameters and results files with
86 /// passed root names (the files may already need per-program
87 /// tagging)
88 void autotag_files(const bfs::path& params_path,
89 const bfs::path& results_path,
90 const String& eval_id_tag
91 //, const bfs::path dest_dir = bfs::path()
92 ) const;
93
94
95 //
96 //- Heading: New virtual functions
97 //
98
99 /// version of wait_local_evaluations() managing of set of individual
100 /// asynchronous evaluations
101 virtual void wait_local_evaluation_sequence(PRPQueue& prp_queue) = 0;
102 /// version of test_local_evaluations() managing of set of individual
103 /// asynchronous evaluations
104 virtual void test_local_evaluation_sequence(PRPQueue& prp_queue) = 0;
105
106 /// bookkeeping of process and evaluation ids for asynchronous maps
107 virtual void map_bookkeeping(pid_t pid, int fn_eval_id) = 0;
108
109 /// Spawn the evaluation by managing the input filter, analysis drivers,
110 /// and output filter. Called from derived_map() & derived_map_asynch().
111 virtual pid_t create_evaluation_process(bool block_flag) = 0;
112
113 //
114 //- Heading: Methods
115 //
116
117 /// batch version of wait_local_evaluations()
118 void wait_local_evaluation_batch(PRPQueue& prp_queue);
119 /// batch version of test_local_evaluations()
120 void test_local_evaluation_batch(PRPQueue& prp_queue);
121
122 /// execute analyses synchronously on the local processor
123 void synchronous_local_analyses(int start, int end, int step);
124
125 //void clear_bookkeeping(); // virtual fn redefinition: clear processIdMap
126
127 /// define modified filenames from user input by handling Unix temp
128 /// file and optionally tagging with given eval_id_tag
129 void define_filenames(const String& eval_id_tag);
130
131 /// write the parameters data and response request data to one or
132 /// more parameters files (using one or more invocations of
133 /// write_parameters_file()) in either standard or aprepro format
134 void write_parameters_files(const Variables& vars, const ActiveSet& set,
135 const Response& response, const int id);
136
137 /// read the response object from one or more results files using
138 /// full eval_id_tag passed
139 void read_results_files(Response& response, const int id,
140 const String& eval_id_tag);
141
142 /// construct a work directory name (tmp or named), with optional tag
143 bfs::path get_workdir_name();
144
145 /// set PATH, environment variables, and change directory prior to
146 /// fork/system/spawn
147 void prepare_process_environment();
148
149 /// reset PATH and current directory after system/spawn (workdir case)
150 void reset_process_environment();
151
152 //
153 //- Heading: Data
154 //
155
156 /// flags tagging of parameter/results files
157 bool fileTagFlag;
158 /// flags retention of parameter/results files
159 bool fileSaveFlag;
160 /// flag indicating use of passing of filenames as command line arguments to
161 /// the analysis drivers and input/output filters
162 bool commandLineArgs;
163 /// flag indicating use of the APREPRO (the Sandia "A PRE PROcessor" utility)
164 /// format for parameter files
165 bool apreproFlag;
166 /// results file format
167 unsigned short resultsFileFormat;
168 /// flag indicating the need for separate parameters files for multiple
169 /// analysis drivers
170 bool multipleParamsFiles;
171
172 /// the name of the input filter (input_filter user specification)
173 std::string iFilterName;
174 /// the name of the output filter (output_filter user specification)
175 std::string oFilterName;
176 /// the names of the analysis code programs (analysis_drivers user
177 /// specification)
178 std::vector<String> programNames;
179 /// the name of the parameters file from user specification
180 std::string specifiedParamsFileName;
181 /// the parameters file name actually used (modified with tagging or
182 /// temp files); only valid from define_filenames to write_parameters_files
183 std::string paramsFileName;
184
185 /// actual, qualified name of the params file written, possibly with workdir
186 std::string paramsFileWritten;
187
188 /// the name of the results file from user specification
189 std::string specifiedResultsFileName;
190 /// the results file name actually used (modified with tagging or
191 /// temp files); only valid from define_filenames to write_parameters_files
192 std::string resultsFileName;
193
194 /// actual, qualified name of the results file written, possibly with workdir
195 std::string resultsFileWritten;
196
197 /// complete evalIdTag, possibly including hierarchical tagging and
198 /// final eval id, but not program numbers, for passing to
199 /// write_parameters_files
200 std::string fullEvalId;
201
202 /// by default analysis code interfaces delete results files if they
203 /// exist; user may override with this flag and we'll try to gather
204 /// and only fork if needed
205 bool allowExistingResults;
206
207 /// Maps function evaluation ID to triples (parameters, results, and
208 /// workdir) paths used in spawning function evaluations. Workdir
209 /// will be empty if not created specifically for this eval.
210 std::map<int, PathTriple> fileNameMap;
211
212 // work_directory creation/removal controls
213
214 /// whether to use a work_directory
215 bool useWorkdir;
216 /// work_directory name, if specified...
217 std::string workDirName;
218 /// whether to tag the working directory
219 bool dirTag;
220 /// whether dir_save was specified
221 bool dirSave;
222 /// active working directory for this evaluation; valid only from
223 /// define_filenames to create_evaluation_process
224 bfs::path curWorkdir;
225
226 /// non-empty if created for this eval; valid only from
227 /// define_filenames to write_parameters_files
228 bfs::path createdDir;
229
230 // work directory population controls
231
232 /// template directory (if specified)
233 StringArray linkFiles;
234 /// template files (if specified)
235 StringArray copyFiles;
236 /// whether to replace existing files
237 bool templateReplace;
238
239 private:
240
241 //
242 //- Heading: Convenience functions
243 //
244
245 /// write the variables, active set vector, derivative variables vector,
246 /// and analysis components to the specified parameters file in either
247 /// standard or aprepro format
248 void write_parameters_file(const Variables& vars, const ActiveSet& set,
249 const Response& response, const std::string& prog,
250 const std::vector<String>& an_comps,
251 const std::string& params_fname,
252 const bool file_mode_out = true);
253
254 /// Open and read the results file at path, properly handling errors
255 void read_results_file(Response &response, const bfs::path &path,
256 const int id);
257 //
258 //- Heading: Data
259 //
260
261 };
262
263
264 /** Execute analyses synchronously in succession on the local
265 processor (start to end in step increments). Modeled after
266 ApplicationInterface::synchronous_local_evaluations(). */
267 inline void ProcessApplicInterface::
synchronous_local_analyses(int start,int end,int step)268 synchronous_local_analyses(int start, int end, int step)
269 {
270 for (int analysis_id=start; analysis_id<=end; analysis_id+=step)
271 synchronous_local_analysis(analysis_id);
272 }
273
274
analysis_drivers() const275 inline const StringArray& ProcessApplicInterface::analysis_drivers() const
276 { return programNames; }
277
278 } // namespace Dakota
279
280 #endif
281