Nektar++
NekMesh.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: NekMesh.cpp
4 //
5 // For more information, please see: http://www.nektar.info/
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description: Mesh conversion utility.
32 //
33 ////////////////////////////////////////////////////////////////////////////////
34 
35 #include <string>
36 #include <boost/algorithm/string.hpp>
39 #include <boost/program_options.hpp>
40 #include <boost/asio/ip/host_name.hpp>
41 #include <boost/format.hpp>
42 
43 #include <NekMesh/Module/Module.h>
44 
45 using namespace std;
46 using namespace Nektar::NekMesh;
47 
48 namespace po = boost::program_options;
49 namespace ip = boost::asio::ip;
50 
51 int main(int argc, char* argv[])
52 {
53  po::options_description desc("Available options");
54  desc.add_options()
55  ("help,h", "Produce this help message.")
56  ("modules-list,l", "Print the list of available modules.")
57  ("modules-opt,p", po::value<string>(),
58  "Print options for a module.")
59  ("module,m", po::value<vector<string> >(),
60  "Specify modules which are to be used.")
61  ("verbose,v", "Enable verbose output.");
62 
63  po::options_description hidden("Hidden options");
64  hidden.add_options()
65  ("input-file", po::value<vector<string> >(), "Input filename");
66 
67  po::options_description cmdline_options;
68  cmdline_options.add(hidden).add(desc);
69 
70  po::options_description visible("Allowed options");
71  visible.add(desc);
72 
73  po::positional_options_description p;
74  p.add("input-file", -1);
75 
76  po::variables_map vm;
77 
78  try
79  {
80  po::store(po::command_line_parser(argc, argv).
81  options(cmdline_options).positional(p).run(), vm);
82  po::notify(vm);
83  }
84  catch (const std::exception& e)
85  {
86  cerr << e.what() << endl;
87  cerr << desc;
88  return 1;
89  }
90 
91  // Create a logger.
92  auto logOutput = std::make_shared<StreamOutput>(std::cout);
93  Logger log(logOutput, vm.count("verbose") ? VERBOSE : INFO);
94 
95  // Print available modules.
96  if (vm.count("modules-list"))
97  {
99  return 1;
100  }
101 
102  if (vm.count("modules-opt"))
103  {
104  vector<string> tmp1;
105  boost::split(tmp1, vm["modules-opt"].as<string>(), boost::is_any_of(":"));
106 
107  if (tmp1.size() != 2)
108  {
109  cerr << "ERROR: To specify a module, use one of in, out or proc "
110  << "together with the filename; for example in:vtk." << endl;
111  return 1;
112  }
113 
114  if (tmp1[0] != "in" && tmp1[0] != "out" && tmp1[0] != "proc")
115  {
116  cerr << "ERROR: Invalid module type " << tmp1[0] << endl;
117  return 1;
118  }
119 
120  ModuleType t;
121 
122  if (tmp1[0] == "in")
123  {
124  t = eInputModule;
125  }
126  else if (tmp1[0] == "out")
127  {
128  t = eOutputModule;
129  }
130  else if (tmp1[0] == "proc")
131  {
132  t = eProcessModule;
133  }
134 
135  MeshSharedPtr m = std::shared_ptr<Mesh>(new Mesh());
137  ModuleKey(t, tmp1[1]), m);
138  cerr << "Options for module " << tmp1[1] << ":" << endl;
139  mod->SetLogger(log);
140  mod->PrintConfig();
141  return 1;
142  }
143 
144  if (vm.count("help") || vm.count("input-file") != 1) {
145  cerr << "Usage: NekMesh [options] inputfile.ext1 outputfile.ext2"
146  << endl;
147  cout << desc;
148  return 1;
149  }
150 
151  vector<string> inout = vm["input-file"].as<vector<string> >();
152 
153  if (inout.size() < 2)
154  {
155  cerr << "ERROR: You must specify an input and output file." << endl;
156  return 1;
157  }
158 
159  /*
160  * Process list of modules. Each element of the vector of module strings can
161  * be in the following form:
162  *
163  * modname:arg1=a:arg2=b:arg3=c:arg4:arg5=asd
164  *
165  * where the only required argument is 'modname', specifing the name of the
166  * module to load.
167  */
168 
169  MeshSharedPtr mesh = std::shared_ptr<Mesh>(new Mesh());
170 
171  // Add provenance information to mesh.
172  stringstream ss;
173  for(int i = 1; i < argc; i++)
174  {
175  ss << argv[i] << " ";
176  }
177  mesh->m_metadata["NekMeshCommandLine"] = ss.str();
178 
179  vector<ModuleSharedPtr> modules;
180  vector<string> modcmds;
181 
182  if (vm.count("module"))
183  {
184  modcmds = vm["module"].as<vector<string> >();
185  }
186 
187  // Add input and output modules to beginning and end of this vector.
188  modcmds.insert (modcmds.begin(), inout[0]);
189  modcmds.push_back(inout[1]);
190 
191  // Keep track of maximum string length for nicer verbose output.
192  size_t maxModName = 0;
193 
194  for (int i = 0; i < modcmds.size(); ++i)
195  {
196  // First split each command by the colon separator.
197  vector<string> tmp1;
198  ModuleKey module;
199  int offset = 1;
200 
201  boost::split(tmp1, modcmds[i], boost::is_any_of(":"));
202 
203  if (i == 0 || i == modcmds.size() - 1)
204  {
205  module.first = (i == 0 ? eInputModule : eOutputModule);
206 
207  // If no colon detected, automatically detect mesh type from
208  // file extension. Otherwise override and use tmp1[1] as the
209  // module to load. This also allows us to pass options to
210  // input/output modules. So, for example, to override
211  // filename.xml to be read as vtk, you use:
212  //
213  // filename.xml:vtk:opt1=arg1:opt2=arg2
214  if (tmp1.size() == 1)
215  {
216  int dot = tmp1[0].find_last_of('.') + 1;
217  string ext = tmp1[0].substr(dot, tmp1[0].length() - dot);
218 
219  if (ext == "gz")
220  {
221  string tmp = tmp1[0].substr(0, tmp1[0].length() - 3);
222  dot = tmp.find_last_of('.') + 1;
223  ext = tmp.substr(dot, tmp.length() - dot);
224  }
225 
226  module.second = ext;
227  tmp1.push_back(string(i == 0 ? "infile=" : "outfile=")+tmp1[0]);
228  }
229  else
230  {
231  module.second = tmp1[1];
232  tmp1.push_back(string(i == 0 ? "infile=" : "outfile=")+tmp1[0]);
233  offset++;
234  }
235  }
236  else
237  {
238  module.first = eProcessModule;
239  module.second = tmp1[0];
240  }
241 
242  // Create module.
243  ModuleSharedPtr mod = GetModuleFactory().CreateInstance(module,mesh);
244  mod->SetLogger(log);
245  modules.push_back(mod);
246 
247  // Set options for this module.
248  for (int j = offset; j < tmp1.size(); ++j)
249  {
250  vector<string> tmp2;
251  boost::split(tmp2, tmp1[j], boost::is_any_of("="));
252 
253  if (tmp2.size() == 1)
254  {
255  mod->RegisterConfig(tmp2[0]);
256  }
257  else if (tmp2.size() == 2)
258  {
259  mod->RegisterConfig(tmp2[0], tmp2[1]);
260  }
261  else
262  {
263  cerr << "ERROR: Invalid module configuration: format is "
264  << "either :arg or :arg=val" << endl;
265  return 1;
266  }
267  }
268 
269  // Ensure configuration options have been set.
270  mod->SetDefaults();
271 
272  // Track maximum module name length.
273  std::string modName = mod->GetModuleName();
274  maxModName = std::max(maxModName, modName.length());
275  }
276 
277  log.SetPrefixLen(maxModName);
278 
279  // Run mesh process.
280  for (int i = 0; i < modules.size(); ++i)
281  {
283  t.Start();
284  try
285  {
286  modules[i]->GetLogger().SetPrefixLen(maxModName);
287  modules[i]->Process();
288  }
289  catch (NekMeshError &e)
290  {
291  return 1;
292  }
293  t.Stop();
294 
295  log.SetPrefix(modules[i]->GetModuleName());
296  log(VERBOSE) << " - Elapsed time: "
297  << t.TimePerTest(1) << "s." << std::endl;
298  }
299 
300  return 0;
301 }
int main(int argc, char *argv[])
Definition: NekMesh.cpp:51
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:145
void PrintAvailableClasses(std::ostream &pOut=std::cout)
Prints the available classes to stdout.
Definition: NekFactory.hpp:236
NekDouble TimePerTest(unsigned int n)
Returns amount of seconds per iteration in a test with n iterations.
Definition: Timer.cpp:62
std::pair< ModuleType, std::string > ModuleKey
Definition: Module.h:290
std::shared_ptr< Module > ModuleSharedPtr
Definition: Module.h:294
ModuleFactory & GetModuleFactory()
Definition: Module.cpp:49
scalarT< T > log(scalarT< T > in)
Definition: scalar.hpp:278