Nektar++
Functions
NekMesh.cpp File Reference
#include <LibUtilities/BasicConst/GitRevision.h>
#include <LibUtilities/BasicUtils/Timer.h>
#include <boost/algorithm/string.hpp>
#include <boost/asio/ip/host_name.hpp>
#include <boost/format.hpp>
#include <boost/program_options.hpp>
#include <string>
#include <NekMesh/Module/Module.h>

Go to the source code of this file.

Functions

int main (int argc, char *argv[])
 

Function Documentation

◆ main()

int main ( int  argc,
char *  argv[] 
)

Definition at line 51 of file NekMesh.cpp.

52 {
53  po::options_description desc("Available options");
54 
55  // clang-format off
56  desc.add_options()
57  ("help,h", "Produce this help message.")
58  ("modules-list,l", "Print the list of available modules.")
59  ("modules-opt,p", po::value<string>(),
60  "Print options for a module.")
61  ("module,m", po::value<vector<string> >(),
62  "Specify modules which are to be used.")
63  ("verbose,v", "Enable verbose output.");
64  // clang-format on
65 
66  po::options_description hidden("Hidden options");
67 
68  // clang-format off
69  hidden.add_options()
70  ("input-file", po::value<vector<string> >(), "Input filename");
71  // clang-format on
72 
73  po::options_description cmdline_options;
74  cmdline_options.add(hidden).add(desc);
75 
76  po::options_description visible("Allowed options");
77  visible.add(desc);
78 
79  po::positional_options_description p;
80  p.add("input-file", -1);
81 
82  po::variables_map vm;
83 
84  try
85  {
86  po::store(po::command_line_parser(argc, argv)
87  .options(cmdline_options)
88  .positional(p)
89  .run(),
90  vm);
91  po::notify(vm);
92  }
93  catch (const std::exception &e)
94  {
95  cerr << e.what() << endl;
96  cerr << desc;
97  return 1;
98  }
99 
100  // Create a logger.
101  auto logOutput = std::make_shared<StreamOutput>(std::cout);
102  Logger log(logOutput, vm.count("verbose") ? VERBOSE : INFO);
103 
104  // Print available modules.
105  if (vm.count("modules-list"))
106  {
108  return 1;
109  }
110 
111  if (vm.count("modules-opt"))
112  {
113  vector<string> tmp1;
114  boost::split(tmp1, vm["modules-opt"].as<string>(),
115  boost::is_any_of(":"));
116 
117  if (tmp1.size() != 2)
118  {
119  cerr << "ERROR: To specify a module, use one of in, out or proc "
120  << "together with the filename; for example in:vtk." << endl;
121  return 1;
122  }
123 
124  if (tmp1[0] != "in" && tmp1[0] != "out" && tmp1[0] != "proc")
125  {
126  cerr << "ERROR: Invalid module type " << tmp1[0] << endl;
127  return 1;
128  }
129 
130  ModuleType t;
131 
132  if (tmp1[0] == "in")
133  {
134  t = eInputModule;
135  }
136  else if (tmp1[0] == "out")
137  {
138  t = eOutputModule;
139  }
140  else if (tmp1[0] == "proc")
141  {
142  t = eProcessModule;
143  }
144 
145  MeshSharedPtr m = std::shared_ptr<Mesh>(new Mesh());
146  ModuleSharedPtr mod =
147  GetModuleFactory().CreateInstance(ModuleKey(t, tmp1[1]), m);
148  cerr << "Options for module " << tmp1[1] << ":" << endl;
149  mod->SetLogger(log);
150  mod->PrintConfig();
151  return 1;
152  }
153 
154  if (vm.count("help") || vm.count("input-file") != 1)
155  {
156  cerr << "Usage: NekMesh [options] inputfile.ext1 outputfile.ext2"
157  << endl;
158  cout << desc;
159  return 1;
160  }
161 
162  vector<string> inout = vm["input-file"].as<vector<string>>();
163 
164  if (inout.size() < 2)
165  {
166  cerr << "ERROR: You must specify an input and output file." << endl;
167  return 1;
168  }
169 
170  /*
171  * Process list of modules. Each element of the vector of module strings can
172  * be in the following form:
173  *
174  * modname:arg1=a:arg2=b:arg3=c:arg4:arg5=asd
175  *
176  * where the only required argument is 'modname', specifing the name of the
177  * module to load.
178  */
179 
180  MeshSharedPtr mesh = std::shared_ptr<Mesh>(new Mesh());
181 
182  // Add provenance information to mesh.
183  stringstream ss;
184  for (int i = 1; i < argc; i++)
185  {
186  ss << argv[i] << " ";
187  }
188  mesh->m_metadata["NekMeshCommandLine"] = ss.str();
189 
190  vector<ModuleSharedPtr> modules;
191  vector<string> modcmds;
192 
193  if (vm.count("module"))
194  {
195  modcmds = vm["module"].as<vector<string>>();
196  }
197 
198  // Add input and output modules to beginning and end of this vector.
199  modcmds.insert(modcmds.begin(), inout[0]);
200  modcmds.push_back(inout[1]);
201 
202  // Keep track of maximum string length for nicer verbose output.
203  size_t maxModName = 0;
204 
205  for (int i = 0; i < modcmds.size(); ++i)
206  {
207  // First split each command by the colon separator.
208  vector<string> tmp1;
209  ModuleKey module;
210  int offset = 1;
211 
212  boost::split(tmp1, modcmds[i], boost::is_any_of(":"));
213 
214  if (i == 0 || i == modcmds.size() - 1)
215  {
216  module.first = (i == 0 ? eInputModule : eOutputModule);
217 
218  // If no colon detected, automatically detect mesh type from
219  // file extension. Otherwise override and use tmp1[1] as the
220  // module to load. This also allows us to pass options to
221  // input/output modules. So, for example, to override
222  // filename.xml to be read as vtk, you use:
223  //
224  // filename.xml:vtk:opt1=arg1:opt2=arg2
225  if (tmp1.size() == 1)
226  {
227  int dot = tmp1[0].find_last_of('.') + 1;
228  string ext = tmp1[0].substr(dot, tmp1[0].length() - dot);
229 
230  if (ext == "gz")
231  {
232  string tmp = tmp1[0].substr(0, tmp1[0].length() - 3);
233  dot = tmp.find_last_of('.') + 1;
234  ext = tmp.substr(dot, tmp.length() - dot);
235  }
236 
237  module.second = ext;
238  tmp1.push_back(string(i == 0 ? "infile=" : "outfile=") +
239  tmp1[0]);
240  }
241  else
242  {
243  module.second = tmp1[1];
244  tmp1.push_back(string(i == 0 ? "infile=" : "outfile=") +
245  tmp1[0]);
246  offset++;
247  }
248  }
249  else
250  {
251  module.first = eProcessModule;
252  module.second = tmp1[0];
253  }
254 
255  // Create module.
256  ModuleSharedPtr mod = GetModuleFactory().CreateInstance(module, mesh);
257  mod->SetLogger(log);
258  modules.push_back(mod);
259 
260  // Set options for this module.
261  for (int j = offset; j < tmp1.size(); ++j)
262  {
263  vector<string> tmp2;
264  boost::split(tmp2, tmp1[j], boost::is_any_of("="));
265 
266  if (tmp2.size() == 1)
267  {
268  mod->RegisterConfig(tmp2[0]);
269  }
270  else if (tmp2.size() == 2)
271  {
272  mod->RegisterConfig(tmp2[0], tmp2[1]);
273  }
274  else
275  {
276  cerr << "ERROR: Invalid module configuration: format is "
277  << "either :arg or :arg=val" << endl;
278  return 1;
279  }
280  }
281 
282  // Ensure configuration options have been set.
283  mod->SetDefaults();
284 
285  // Track maximum module name length.
286  std::string modName = mod->GetModuleName();
287  maxModName = std::max(maxModName, modName.length());
288  }
289 
290  log.SetPrefixLen(maxModName);
291 
292  // Run mesh process.
293  for (int i = 0; i < modules.size(); ++i)
294  {
296  t.Start();
297  try
298  {
299  modules[i]->GetLogger().SetPrefixLen(maxModName);
300  modules[i]->Process();
301  }
302  catch (NekMeshError &e)
303  {
304  return 1;
305  }
306  t.Stop();
307 
308  log.SetPrefix(modules[i]->GetModuleName());
309  log(VERBOSE) << " - Elapsed time: " << t.TimePerTest(1) << "s."
310  << std::endl;
311  }
312 
313  return 0;
314 }
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
void PrintAvailableClasses(std::ostream &pOut=std::cout)
Prints the available classes to stdout.
Definition: NekFactory.hpp:232
NekDouble TimePerTest(unsigned int n)
Returns amount of seconds per iteration in a test with n iterations.
Definition: Timer.cpp:68
std::pair< ModuleType, std::string > ModuleKey
Definition: Module.h:285
std::shared_ptr< Module > ModuleSharedPtr
Definition: Module.h:289
ModuleFactory & GetModuleFactory()
Definition: Module.cpp:49
scalarT< T > log(scalarT< T > in)
Definition: scalar.hpp:300

References Nektar::LibUtilities::NekFactory< tKey, tBase, tParam >::CreateInstance(), Nektar::FieldUtils::eInputModule, Nektar::FieldUtils::eOutputModule, Nektar::FieldUtils::eProcessModule, Nektar::FieldUtils::GetModuleFactory(), tinysimd::log(), CG_Iterations::Mesh, CellMLToNektar.cellml_metadata::p, Nektar::LibUtilities::NekFactory< tKey, tBase, tParam >::PrintAvailableClasses(), CellMLToNektar.translators::run(), Nektar::LibUtilities::Timer::Start(), Nektar::LibUtilities::Timer::Stop(), and Nektar::LibUtilities::Timer::TimePerTest().