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