OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
SampleCmd.cpp
Go to the documentation of this file.
1 #include "Sample/SampleCmd.h"
2 #include "Sample/Sampler.h"
3 #include "Sample/OpalSample.h"
4 #include "Sample/RNGStream.h"
5 
6 #include "Optimize/DVar.h"
7 #include "Optimize/Objective.h"
9 
10 #include "Attributes/Attributes.h"
13 #include "Utilities/Util.h"
14 
15 #include "Utility/IpplInfo.h"
16 #include "Utility/IpplTimings.h"
17 #include "Track/Track.h"
18 
19 #include "Sample/SamplePilot.h"
20 #include "Util/CmdArguments.h"
21 #include "Util/OptPilotException.h"
22 
23 #include "Comm/CommSplitter.h"
27 
29 #include "Expression/FromFile.h"
30 #include "Expression/SumErrSq.h"
32 #include "Expression/RadialPeak.h"
37 
38 #include <boost/filesystem.hpp>
39 
40 #include <map>
41 #include <set>
42 #include <string>
43 #include <vector>
44 
45 extern Inform *gmsg;
46 
47 namespace {
48  enum {
49  INPUT,
50  OUTPUT,
51  OUTDIR,
52  OBJECTIVES,
53  STOREOBJECTIVES,
54  DVARS,
55  SAMPLINGS,
56  NUMMASTERS,
57  NUMCOWORKERS,
58  TEMPLATEDIR,
59  FIELDMAPDIR,
60  DISTDIR,
61  RASTER,
62  SEED,
63  KEEP,
64  RESTART_FILE,
65  RESTART_STEP,
66  JSON_DUMP_FREQ,
67  SIZE
68  };
69 }
70 
72  Action(SIZE, "SAMPLE",
73  "The \"SAMPLE\" command initiates sampling.") {
75  ("INPUT", "Path to input file");
77  ("OUTPUT", "Name used in output file sample");
79  ("OUTDIR", "Name of directory used to run and store sample output files");
81  ("OBJECTIVES", "List of expressions to evaluate and store");
82  itsAttr[STOREOBJECTIVES] = Attributes::makeStringArray
83  ("STOREOBJECTIVES", "List of stat variables to store");
85  ("DVARS", "List of sampling variables to be used");
87  ("SAMPLINGS", "List of sampling methods to be used");
88  itsAttr[NUMMASTERS] = Attributes::makeReal
89  ("NUM_MASTERS", "Number of master nodes");
90  itsAttr[NUMCOWORKERS] = Attributes::makeReal
91  ("NUM_COWORKERS", "Number processors per worker");
92  itsAttr[TEMPLATEDIR] = Attributes::makeString
93  ("TEMPLATEDIR", "Directory where templates are stored");
94  itsAttr[FIELDMAPDIR] = Attributes::makeString
95  ("FIELDMAPDIR", "Directory where field maps are stored");
97  ("DISTDIR", "Directory where distributions are stored");
99  ("RASTER", "Scan full space given by design variables (default: true)", true);
101  ("SEED", "Seed for global random number generator (default: 42)", 42);
103  ("KEEP", "List of files to keep for each simulation. (default: all files kept)");
104  itsAttr[RESTART_FILE] = Attributes::makeString
105  ("RESTART_FILE", "H5 file to restart the OPAL simulations from (optional)", "");
106  itsAttr[RESTART_STEP] = Attributes::makeReal
107  ("RESTART_STEP", "Restart from given H5 step (optional)",
109  itsAttr[JSON_DUMP_FREQ] = Attributes::makeReal
110  ("JSON_DUMP_FREQ", "Defines how often new individuals are appended to the final JSON file, "
111  "i.e. every time JSON_DUMP_FREQ samples finished they are written (optional)",
114 }
115 
116 SampleCmd::SampleCmd(const std::string &name, SampleCmd *parent):
117  Action(name, parent)
118 { }
119 
121 { }
122 
123 SampleCmd *SampleCmd::clone(const std::string &name) {
124  return new SampleCmd(name, this);
125 }
126 
128 
129  namespace fs = boost::filesystem;
130 
131  auto opal = OpalData::getInstance();
132  opal->setOptimizerFlag();
133 
134  fs::path inputfile(Attributes::getString(itsAttr[INPUT]));
135 
136  unsigned int seed = Attributes::getReal(itsAttr[SEED]);
138 
139  std::vector<std::string> objectivesstr = Attributes::getStringArray(itsAttr[OBJECTIVES]);
140  // FIXME Open issue #250 (https://gitlab.psi.ch/OPAL/src/issues/250)
141  std::vector<std::string> storeobjstr = Attributes::getStringArray(itsAttr[STOREOBJECTIVES]);
142  std::vector<std::string> dvarsstr = Attributes::getStringArray(itsAttr[DVARS]);
143  Expressions::Named_t objectives;
144  DVarContainer_t dvars;
145 
146  std::vector<std::string> filesToKeep = Attributes::getStringArray(itsAttr[KEEP]);
147  std::vector<std::string> sampling = Attributes::getStringArray(itsAttr[SAMPLINGS]);
148 
149  if ( sampling.size() != dvarsstr.size() )
150  throw OpalException("SampleCmd::execute",
151  "Number of sampling methods != number of design variables.");
152 
153  typedef std::map< std::string, std::shared_ptr<SamplingMethod> > sampleMethods_t;
154  sampleMethods_t sampleMethods;
155 
156  std::map<std::string, std::pair<double, double> > vars;
157 
158  for (std::string &name : dvarsstr) {
160  Object *obj = opal->find(name);
161  DVar* dvar = dynamic_cast<DVar*>(obj);
162  if (dvar == nullptr) {
163  throw OpalException("SampleCmd::execute",
164  "The sampling variable " + name + " is not known");
165 
166  }
167  std::string var = dvar->getVariable();
168  double lowerbound = dvar->getLowerBound();
169  double upperbound = dvar->getUpperBound();
170 
171  auto ret = vars.insert(std::make_pair(var, std::make_pair(lowerbound, upperbound)));
172  if (ret.second == false) {
173  throw OpalException("SampleCmd::execute",
174  "There is already a design variable with the variable " + var + " defined");
175  }
176 
177  DVar_t tmp = boost::make_tuple(var, lowerbound, upperbound);
178  dvars.insert(namedDVar_t(name, tmp));
179  }
180 
182 
183  functionDictionary_t funcs;
185  ff = FromFile();
186  funcs.insert(std::pair<std::string, client::function::type>
187  ("fromFile", ff));
188 
189  ff = SumErrSq();
190  funcs.insert(std::pair<std::string, client::function::type>
191  ("sumErrSq", ff));
192 
193  ff = SDDSVariable();
194  funcs.insert(std::pair<std::string, client::function::type>
195  ("sddsVariableAt", ff));
196 
197  ff = RadialPeak();
198  funcs.insert(std::pair<std::string, client::function::type>
199  ("radialPeak", ff));
200 
201  ff = MaxNormRadialPeak();
202  funcs.insert(std::pair<std::string, client::function::type>
203  ("maxNormRadialPeak", ff));
204 
205  ff = NumberOfPeaks();
206  funcs.insert(std::pair<std::string, client::function::type>
207  ("numberOfPeaks", ff));
208 
209  ff = SumErrSqRadialPeak();
210  funcs.insert(std::pair<std::string, client::function::type>
211  ("sumErrSqRadialPeak", ff));
212 
213  ff = ProbeVariable();
214  funcs.insert(std::pair<std::string, client::function::type>
215  ("probVariableWithID", ff));
216 
217  std::string fname = inputfile.stem().native();
218  ff = sameSDDSVariable(fname);
219  funcs.insert(std::pair<std::string, client::function::type>
220  ("statVariableAt", ff));
221 
223 
224  std::set<std::string> objExpressions; // check if all unique objective expressions
225  for (std::string name: objectivesstr) {
227  Object *obj = opal->find(name);
228  Objective* objective = dynamic_cast<Objective*>(obj);
229  if (objective == nullptr) {
230  throw OpalException("OptimizeCmd::execute",
231  "The objective " + name + " is not known");
232 
233  }
234  std::string expr = objective->getExpression();
235  objectives.insert(Expressions::SingleNamed_t(
236  name, new Expressions::Expr_t(expr, funcs)));
237  auto ret = objExpressions.insert(expr);
238  if (ret.second == false) {
239  throw OpalException("OptimizeCmd::execute",
240  "There is already a objective with the expression " + expr + " defined");
241  }
242  }
243 
244  bool raster = Attributes::getBool(itsAttr[RASTER]);
245  size_t modulo = 1;
246  unsigned int nSample = std::numeric_limits<unsigned int>::max();
247 
248  std::set<std::string> names; // check if all unique variables
249  for (size_t i = 0; i < sampling.size(); ++i) {
250  // corresponding sampling method
251  OpalSample *s = OpalSample::find(sampling[i]);
252  if (s == nullptr) {
253  throw OpalException("SampleCmd::execute",
254  "Sampling method not found.");
255  }
256 
257  std::string name = s->getVariable();
258 
259  if ( vars.find(name) == vars.end() ) {
260  throw OpalException("SampleCmd::execute",
261  "Variable '" + name + "' not a DVAR.");
262  }
263 
264  auto ret = names.insert(name);
265  if (ret.second == false) {
266  throw OpalException("SampleCmd::execute",
267  "There is already a sampling method with the variable " + name + " defined");
268  }
269 
270  s->initialize(name,
271  vars[name].first,
272  vars[name].second,
273  modulo,
274  raster);
275 
276  if ( raster )
277  modulo *= s->getSize();
278 
279  nSample = std::min(nSample, s->getSize());
280 
281  sampleMethods[name] = s->sampleMethod_m;
282  }
283 
284  // Setup/Configuration
286  typedef OpalSimulation Sim_t;
287 
289  typedef SocialNetworkGraph< NoCommTopology > SolPropagationGraph_t;
290 
292 
294 
295  std::vector<std::string> arguments(opal->getArguments());
296  std::vector<char*> argv;
297  std::map<unsigned int, std::string> argumentMapper({
298  {INPUT, "inputfile"},
299  {OUTPUT, "outfile"},
300  {OUTDIR, "outdir"},
301  {NUMMASTERS, "num-masters"},
302  {NUMCOWORKERS, "num-coworkers"},
303  {RESTART_FILE, "restartfile"},
304  {RESTART_STEP, "restartstep"},
305  {JSON_DUMP_FREQ, "jsonDumpFreq"}
306  });
307 
308  auto it = argumentMapper.end();
309  for (unsigned int i = 0; i < SIZE; ++ i) {
310  if ((it = argumentMapper.find(i)) != argumentMapper.end()) {
311  std::string type = itsAttr[i].getType();
312  if (type == "string") {
313  if (Attributes::getString(itsAttr[i]) != "") {
314  std::string argument = "--" + (*it).second + "=" + Attributes::getString(itsAttr[i]);
315  arguments.push_back(argument);
316  }
317  } else if (type == "real") {
318  if (itsAttr[i]) {
319  std::string val = std::to_string (Attributes::getReal(itsAttr[i]));
320  size_t last = val.find_last_not_of('0');
321  if (val[last] != '.') ++ last;
322  val.erase (last, std::string::npos );
323  std::string argument = "--" + (*it).second + "=" + val;
324  arguments.push_back(argument);
325  }
326  } else if (type == "logical") {
327  if (itsAttr[i]) {
328  std::string argument = "--" + (*it).second + "=" + std::to_string(Attributes::getBool(itsAttr[i]));
329  arguments.push_back(argument);
330  }
331  }
332  }
333  }
334 
335  if ( raster )
336  nSample = modulo;
337 
338  arguments.push_back("--nsamples=" + std::to_string(nSample));
339 
340  if (Attributes::getString(itsAttr[INPUT]) == "") {
341  throw OpalException("SampleCmd::execute",
342  "The argument INPUT has to be provided");
343  }
344 
345  if (Attributes::getString(itsAttr[OUTDIR]) != "") {
346  fs::path dir(Attributes::getString(itsAttr[OUTDIR]));
347  if (dir.is_relative()) {
348  fs::path path = fs::path(std::string(getenv("PWD")));
349  path /= dir;
350  dir = path;
351  }
352 
353  if (!fs::exists(dir)) {
354  fs::create_directory(dir);
355  }
356  std::string argument = "--simtmpdir=" + dir.native();
357  arguments.push_back(argument);
358  }
359 
360  if (Attributes::getString(itsAttr[TEMPLATEDIR]) != "") {
361  fs::path dir(Attributes::getString(itsAttr[TEMPLATEDIR]));
362  if (dir.is_relative()) {
363  fs::path path = fs::path(std::string(getenv("PWD")));
364  path /= dir;
365  dir = path;
366  }
367 
368  std::string argument = "--templates=" + dir.native();
369  arguments.push_back(argument);
370  }
371 
372  if (Attributes::getString(itsAttr[FIELDMAPDIR]) != "") {
373  fs::path dir(Attributes::getString(itsAttr[FIELDMAPDIR]));
374  if (dir.is_relative()) {
375  fs::path path = fs::path(std::string(getenv("PWD")));
376  path /= dir;
377  dir = path;
378  }
379 
380  setenv("FIELDMAPS", dir.c_str(), 1);
381  }
382 
383  if (Attributes::getString(itsAttr[DISTDIR]) != "") {
384  fs::path dir(Attributes::getString(itsAttr[DISTDIR]));
385  if (dir.is_relative()) {
386  fs::path path = fs::path(std::string(getenv("PWD")));
387  path /= dir;
388  dir = path;
389  }
390 
391  setenv("DISTRIBUTIONS", dir.c_str(), 1);
392  }
393 
394  {
395  std::string tmplFile = Attributes::getString(itsAttr[INPUT]);
396  size_t pos = tmplFile.find_last_of("/");
397  if(pos != std::string::npos)
398  tmplFile = tmplFile.substr(pos+1);
399  pos = tmplFile.find(".");
400  tmplFile = tmplFile.substr(0,pos);
401  tmplFile = Attributes::getString(itsAttr[TEMPLATEDIR]) + "/" + tmplFile + ".tmpl";
402 
403  std::ifstream infile(tmplFile.c_str());
404 
405  std::map<std::string, short> dvarCheck;
406  auto itr = dvars.begin();
407  for (; itr != dvars.end(); ++ itr) {
408  dvarCheck.insert(std::make_pair(boost::get<0>(itr->second), 0));
409  }
410 
411  while(infile.good()) {
412  std::string line;
413  std::getline(infile, line, '\n');
414 
415  //XXX doing the inverse would be better
416  for(auto &check: dvarCheck) {
417  size_t pos = line.find("_" + check.first + "_");
418  if (pos != std::string::npos &&
419  dvarCheck.find(check.first) != dvarCheck.end()) {
420  dvarCheck.at(check.first) = 1;
421  }
422  }
423  }
424  infile.close();
425 
426  for (auto itr = dvarCheck.begin(); itr != dvarCheck.end(); ++ itr) {
427  if (itr->second == 0) {
428  throw OpalException("SampleCmd::execute()",
429  "Couldn't find the design variable '" + itr->first + "' in '" + tmplFile + "'!");
430  }
431  }
432  }
433 
434  *gmsg << endl;
435  for (size_t i = 0; i < arguments.size(); ++ i) {
436  argv.push_back(const_cast<char*>(arguments[i].c_str()));
437  *gmsg << arguments[i] << " ";
438  }
439  *gmsg << endl;
440 
441  Inform *origGmsg = gmsg;
442  gmsg = 0;
443  try {
444  CmdArguments_t args(new CmdArguments(argv.size(), &argv[0]));
445 
446  boost::shared_ptr<Comm_t> comm(new Comm_t(args, MPI_COMM_WORLD));
447  if (comm->isWorker())
449 
450  if ( comm->isOptimizer() ) {
451  for (sampleMethods_t::iterator it = sampleMethods.begin();
452  it != sampleMethods.end(); ++it)
453  {
454  it->second->allocate(args, comm->getBundle());
455  }
456  }
457 
458  boost::scoped_ptr<pilot_t> pi(new pilot_t(args, comm, funcs, dvars,
459  objectives, sampleMethods,
460  storeobjstr, filesToKeep));
461  if (comm->isWorker())
462  popEnvironment();
463 
464  } catch (OptPilotException &e) {
465  std::cout << "Exception caught: " << e.what() << std::endl;
466  MPI_Abort(MPI_COMM_WORLD, -100);
467  }
468  gmsg = origGmsg;
469 }
470 
472  Ippl::stash();
474  Track::stash();
476 }
477 
479  Ippl::pop();
482  Track::pop();
483 }
static void stash()
int seed
The current random seed.
Definition: Options.cpp:41
virtual const char * what() const
static void stash()
Definition: Track.cpp:95
std::string getExpression() const
Definition: Objective.cpp:31
std::pair< std::string, Expressions::Expr_t * > SingleNamed_t
Definition: Expression.h:48
constexpr double e
The value of .
Definition: Physics.h:40
Concrete implementation of an Opal simulation wrapper.
void popEnvironment()
Definition: SampleCmd.cpp:478
Definition: DVar.h:6
The base class for all OPAL actions.
Definition: Action.h:30
std::string getVariable() const
Definition: DVar.cpp:37
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:123
The base class for all OPAL exceptions.
Definition: OpalException.h:28
virtual void execute()
Execute the command.
Definition: SampleCmd.cpp:127
boost::shared_ptr< CmdArguments > CmdArguments_t
Definition: CmdArguments.h:169
static void stash()
Definition: IpplInfo.cpp:1102
Inform * gmsg
Definition: Main.cpp:21
std::string toUpper(const std::string &str)
Definition: Util.cpp:130
Expression to be evaluated in the framework.
Definition: Expression.h:75
FRONT * fs
Definition: hypervolume.cpp:59
unsigned int getSize() const
Definition: OpalSample.h:58
std::vector< Attribute > itsAttr
The object attributes (see Attribute.hh).
Definition: Object.h:214
double getLowerBound() const
Definition: DVar.cpp:41
Role assignment according to strategy (that might use hardware network information).
Definition: CommSplitter.h:32
bool getBool(const Attribute &attr)
Return logical value.
Definition: Attributes.cpp:66
Attribute makeStringArray(const std::string &name, const std::string &help)
Create a string array attribute.
Definition: Attributes.cpp:373
static OpalSample * find(const std::string &name)
Find sampling method.
Definition: OpalSample.cpp:79
static OpalData * getInstance()
Definition: OpalData.cpp:209
SampleCmd()
Exemplar constructor.
Definition: SampleCmd.cpp:71
static void setGlobalSeed(unsigned int seed)
Definition: RNGStream.cpp:36
The SAMPLING definition.
Definition: OpalSample.h:15
double getUpperBound() const
Definition: DVar.cpp:45
static void stashInstance()
Definition: OpalData.cpp:225
std::vector< std::string > getStringArray(const Attribute &attr)
Get string array value.
Definition: Attributes.cpp:378
const double pi
Definition: fftpack.cpp:894
void registerOwnership(const AttributeHandler::OwnerType &itsClass) const
Definition: Object.cpp:194
Parsing command line arguments.
Definition: CmdArguments.h:26
std::string getVariable() const
Definition: OpalSample.cpp:180
void stashEnvironment()
Definition: SampleCmd.cpp:471
The SAMPLE command.
Definition: SampleCmd.h:12
std::shared_ptr< SamplingMethod > sampleMethod_m
Definition: OpalSample.h:43
boost::tuple< std::string, double, double > DVar_t
type of design variables
Definition: Types.h:69
std::pair< std::string, DVar_t > namedDVar_t
Definition: Types.h:76
static void pop()
static Track * pop()
Definition: Track.cpp:102
std::map< std::string, DVar_t > DVarContainer_t
Definition: Types.h:77
virtual SampleCmd * clone(const std::string &name)
Make clone.
Definition: SampleCmd.cpp:123
virtual ~SampleCmd()
Definition: SampleCmd.cpp:120
std::map< std::string, Expressions::Expr_t * > Named_t
type of an expressions with a name
Definition: Expression.h:45
void initialize(const std::string &dvarName, double lower, double upper, size_t modulo=1, bool sequence=false)
Definition: OpalSample.cpp:90
static OpalData * popInstance()
Definition: OpalData.cpp:236
The base class for all OPAL objects.
Definition: Object.h:48
Attribute makeBool(const std::string &name, const std::string &help)
Make logical attribute.
Definition: Attributes.cpp:56
boost::function< boost::tuple< double, bool >arguments_t)> type
Definition: function.hpp:21
const std::string name
The sample Pilot (Master): Coordinates requests by sampler to workers.
Definition: SamplePilot.h:33
double FromFile(std::string file, const std::vector< double > &referencePoint)
Modeling social graph (Cartesian neighbors plus additional random link) as underlaying master network...
std::string::iterator iterator
Definition: MSLang.h:16
double getReal(const Attribute &attr)
Return real value.
Definition: Attributes.cpp:217
Definition: Inform.h:41
Attribute makeString(const std::string &name, const std::string &help)
Make string attribute.
Definition: Attributes.cpp:296
std::map< std::string, client::function::type > functionDictionary_t
Definition: Expression.h:27
Attribute makeReal(const std::string &name, const std::string &help)
Make real attribute.
Definition: Attributes.cpp:205
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:95
static void pop()
Definition: IpplInfo.cpp:1173
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
std::string getString(const Attribute &attr)
Get string value.
Definition: Attributes.cpp:307