Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
FieldConvert.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: FieldConvert.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 // License for the specific language governing rights and laimitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description: Field conversion utility.
33 //
34 ////////////////////////////////////////////////////////////////////////////////
35 
36 #include <string>
37 #include <boost/algorithm/string.hpp>
38 #include <boost/program_options.hpp>
39 #include "Module.h"
40 
41 using namespace std;
42 using namespace Nektar;
43 using namespace Nektar::Utilities;
44 
45 int main(int argc, char* argv[])
46 {
47  Timer timer;
48  Timer moduleTimer;
49  timer.Start();
50  po::options_description desc("Available options");
51  desc.add_options()
52  ("help,h",
53  "Produce this help message.")
54  ("modules-list,l",
55  "Print the list of available modules.")
56  ("output-points,n", po::value<int>(),
57  "Output at n equipspaced points along the collapsed coordinates (for .dat, .vtk).")
58  ("output-points-hom-z", po::value<int>(),
59  "Number of planes in the z-direction for output of Homogeneous 1D expansion(for .dat, .vtk).")
60  ("error,e",
61  "Write error of fields for regression checking")
62  ("forceoutput,f",
63  "Force the output to be written without any checks")
64  ("range,r", po::value<string>(),
65  "Define output range i.e. (-r xmin,xmax,ymin,ymax,zmin,zmax) "
66  "in which any vertex is contained.")
67  ("noequispaced","Do not use equispaced output. Currently stops the output-points option")
68  ("nprocs", po::value<int>(),
69  "Used to define nprocs if running serial problem to mimic "
70  "parallel run.")
71  ("npz", po::value<int>(),
72  "Used to define number of partitions in z for Homogeneous1D "
73  "expansions for parallel runs.")
74  ("onlyshape", po::value<string>(),
75  "Only use element with defined shape type i.e. -onlyshape "
76  " Tetrahedron")
77  ("part-only", po::value<int>(),
78  "Partition into specfiied npart partitions and exit")
79  ("part-only-overlapping", po::value<int>(),
80  "Partition into specfiied npart overlapping partitions and exit")
81  ("procid", po::value<int>(),
82  "Process as single procid of a partition of size nproc "
83  "(-nproc must be specified).")
84  ("modules-opt,p", po::value<string>(),
85  "Print options for a module.")
86  ("module,m", po::value<vector<string> >(),
87  "Specify modules which are to be used.")
88  ("shared-filesystem,s", "Using shared filesystem.")
89  ("useSessionVariables",
90  "Use variables defined in session for output")
91  ("verbose,v",
92  "Enable verbose mode.");
93 
94  po::options_description hidden("Hidden options");
95  hidden.add_options()
96  ("input-file", po::value<vector<string> >(), "Input filename");
97 
98  po::options_description cmdline_options;
99  cmdline_options.add(hidden).add(desc);
100 
101  po::options_description visible("Allowed options");
102  visible.add(desc);
103 
104  po::positional_options_description p;
105  p.add("input-file", -1);
106 
107  po::variables_map vm;
108 
109  try
110  {
111  po::store(po::command_line_parser(argc, argv).
112  options(cmdline_options).positional(p).run(), vm);
113  po::notify(vm);
114  }
115  catch (const std::exception& e)
116  {
117  cerr << e.what() << endl;
118  cerr << desc;
119  return 1;
120  }
121 
122  // Print available modules.
123  if (vm.count("modules-list"))
124  {
126  return 1;
127  }
128 
129  if (vm.count("modules-opt"))
130  {
131  vector<string> tmp1;
132  boost::split(tmp1, vm["modules-opt"].as<string>(),
133  boost::is_any_of(":"));
134 
135  if (tmp1.size() != 2)
136  {
137  cerr << "ERROR: To specify a module, use one of in, out or proc "
138  << "together with the filename; for example in:vtk." << endl;
139  return 1;
140  }
141 
142  if (tmp1[0] != "in" && tmp1[0] != "out" && tmp1[0] != "proc")
143  {
144  cerr << "ERROR: Invalid module type " << tmp1[0] << endl;
145  return 1;
146  }
147 
148  ModuleType t;
149 
150  if (tmp1[0] == "in")
151  {
152  t = eInputModule;
153  }
154  else if (tmp1[0] == "out")
155  {
156  t = eOutputModule;
157  }
158  else if (tmp1[0] == "proc")
159  {
160  t = eProcessModule;
161  }
162 
163  FieldSharedPtr f = boost::shared_ptr<Field>(new Field());
165  ModuleKey(t, tmp1[1]), f);
166  cerr << "Options for module " << tmp1[1] << ":" << endl;
167  mod->PrintConfig();
168  return 1;
169  }
170 
171  if (vm.count("help") || vm.count("input-file") != 1) {
172  cerr << "Usage: FieldConvert [options] inputfile.ext1 outputfile.ext2"
173  << endl;
174  cout << desc;
175  cout << endl;
176  cout << "Example Usage: \n" << endl;
177  cout << "\t FieldConvert -m vorticity file.xml file.fld file_vort.fld "
178  << endl;
179  cout << "(This will add vorticity to file file.fld and put it in a "
180  "new file file_vort.fld) " << endl;
181  cout << endl;
182  cout << "\t FieldConvert file.xml file_vort.fld file_vort.dat " << endl;
183  cout << "(process file_vort.fld and make a tecplot output "
184  "file_vort.dat) " << endl;
185 
186  return 1;
187  }
188 
189  ASSERTL0(vm.count("input-file"),
190  "Must specify input(s) and/or output file.");
191  vector<string> inout = vm["input-file"].as<vector<string> >();
192 
193 
194  /*
195  * Process list of modules. Each element of the vector of module
196  * strings can be in the following form:
197  *
198  * modname:arg1=a:arg2=b:arg3=c:arg4:arg5=asd
199  *
200  * where the only required argument is 'modname', specifing the
201  * name of the module to load.
202  */
203 
204  FieldSharedPtr f = boost::shared_ptr<Field>(new Field());
205  if (LibUtilities::GetCommFactory().ModuleExists("ParallelMPI"))
206  {
207  if(vm.count("procid"))
208  {
209  int nprocs, rank;
210 
211  ASSERTL0(vm.count("nprocs"),
212  "Must specify --nprocs when using --procid option");
213  nprocs = vm["nprocs"].as<int>();
214  rank = vm["procid"].as<int>();
215 
216  f->m_comm = boost::shared_ptr<FieldConvertComm>(
217  new FieldConvertComm(argc, argv, nprocs,rank));
218 
219  // Set forceoutput option. Otherwise only procid 0 will write file
220  vm.insert(std::make_pair("forceoutput", po::variable_value()));
221  }
222  else
223  {
225  "ParallelMPI", argc, argv);
226  }
227  }
228  else
229  {
231  "Serial", argc, argv);
232 
233  }
234 
235  vector<ModuleSharedPtr> modules;
236  vector<string> modcmds;
237 
238 
239  if (vm.count("verbose"))
240  {
241  f->m_verbose = true;
242  }
243 
244  if (vm.count("module"))
245  {
246  modcmds = vm["module"].as<vector<string> >();
247  }
248 
249  // Add input and output modules to beginning and end of this vector.
250  modcmds.insert(modcmds.begin(), inout.begin(), inout.end()-1);
251  modcmds.push_back(*(inout.end()-1));
252 
253  int nInput = inout.size()-1;
254 
255  // For special case of part-only or part-only-overlapping options
256  // only require a single input file and so reset the nInputs to be
257  // of size inout.size(). Since the code will exit before reaching
258  // any output module this seems to work as expected
259  if(vm.count("part-only")||vm.count("part-only-overlapping"))
260  {
261  nInput = inout.size();
262  }
263 
264  InputModuleSharedPtr inputModule;
265 
266  for (int i = 0; i < modcmds.size(); ++i)
267  {
268  // First split each command by the colon separator.
269  vector<string> tmp1;
270  ModuleKey module;
271  int offset = 1;
272 
273  boost::split(tmp1, modcmds[i], boost::is_any_of(":"));
274 
275  if (i < nInput || i == modcmds.size() - 1)
276  {
277  module.first = (i < nInput ? eInputModule : eOutputModule);
278 
279  // If no colon detected, automatically detect mesh type from
280  // file extension. Otherwise override and use tmp1[1] as the
281  // module to load. This also allows us to pass options to
282  // input/output modules. So, for example, to override
283  // filename.xml to be read as vtk, you use:
284  //
285  // filename.xml:vtk:opt1=arg1:opt2=arg2
286  if (tmp1.size() == 1)
287  {
288  int dot = tmp1[0].find_last_of('.') + 1;
289  string ext = tmp1[0].substr(dot, tmp1[0].length() - dot);
290 
291  if(ext == "gz")
292  {
293  string tmp2 = tmp1[0].substr(0,dot-1);
294  dot = tmp2.find_last_of('.') + 1;
295  ext = tmp1[0].substr(dot,tmp1[0].length()-dot);
296  }
297 
298  module.second = ext;
299  tmp1.push_back(string(i < nInput ? "infile=" : "outfile=")
300  +tmp1[0]);
301  }
302  else
303  {
304  module.second = tmp1[1];
305  tmp1.push_back(string(i < nInput ? "infile=" : "outfile=")
306  +tmp1[0]);
307  offset++;
308  }
309  }
310  else
311  {
312  module.first = eProcessModule;
313  module.second = tmp1[0];
314  }
315 
316  // Create module.
317  ModuleSharedPtr mod;
318  mod = GetModuleFactory().CreateInstance(module, f);
319  modules.push_back(mod);
320 
321  if (i < nInput)
322  {
323  inputModule = boost::dynamic_pointer_cast<InputModule>(mod);
324  inputModule->AddFile(module.second, tmp1[0]);
325  }
326 
327  // Set options for this module.
328  for (int j = offset; j < tmp1.size(); ++j)
329  {
330  vector<string> tmp2;
331  boost::split(tmp2, tmp1[j], boost::is_any_of("="));
332 
333  if (tmp2.size() == 1)
334  {
335  mod->RegisterConfig(tmp2[0], "1");
336  }
337  else if (tmp2.size() == 2)
338  {
339  mod->RegisterConfig(tmp2[0], tmp2[1]);
340  }
341  else
342  {
343  cerr << "ERROR: Invalid module configuration: format is "
344  << "either :arg or :arg=val" << endl;
345  abort();
346  }
347  }
348 
349  // Ensure configuration options have been set.
350  mod->SetDefaults();
351  }
352 
353  // If any output module has to reset points then set intput modules to match
354  if(vm.count("noequispaced"))
355  {
356  for (int i = 0; i < modules.size(); ++i)
357  {
358  modules[i]->SetRequireEquiSpaced(false);
359  }
360  }
361  else
362  {
363  bool RequiresEquiSpaced = false;
364  for (int i = 0; i < modules.size(); ++i)
365  {
366  if(modules[i]->GetRequireEquiSpaced())
367  {
368  RequiresEquiSpaced = true;
369  }
370  }
371  if (RequiresEquiSpaced)
372  {
373  for (int i = 0; i < modules.size(); ++i)
374  {
375  modules[i]->SetRequireEquiSpaced(true);
376  }
377  }
378  }
379 
380  // Run field process.
381  for (int i = 0; i < modules.size(); ++i)
382  {
383  if(f->m_verbose && f->m_comm->GetRank() == 0)
384  {
385  moduleTimer.Start();
386  }
387  modules[i]->Process(vm);
388  cout.flush();
389  if(f->m_verbose && f->m_comm->GetRank() == 0)
390  {
391  moduleTimer.Stop();
392  NekDouble cpuTime = moduleTimer.TimePerTest(1);
393 
394  stringstream ss;
395  ss << cpuTime << "s";
396  cout << modules[i]->GetModuleName()
397  << " CPU Time: " << setw(8) << left
398  << ss.str() << endl;
399  }
400  }
401 
402  if(f->m_verbose)
403  {
404  if(f->m_comm->GetRank() == 0)
405  {
406  timer.Stop();
407  NekDouble cpuTime = timer.TimePerTest(1);
408 
409  stringstream ss;
410  ss << cpuTime << "s";
411  cout << "Total CPU Time: " << setw(8) << left
412  << ss.str() << endl;
413  }
414  }
415  return 0;
416 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:188
void PrintAvailableClasses(std::ostream &pOut=std::cout)
Prints the available classes to stdout.
Definition: NekFactory.hpp:247
pair< ModuleType, string > ModuleKey
tBaseSharedPtr CreateInstance(tKey idKey BOOST_PP_COMMA_IF(MAX_PARAM) BOOST_PP_ENUM_BINARY_PARAMS(MAX_PARAM, tParam, x))
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:162
STL namespace.
CommFactory & GetCommFactory()
Definition: Comm.cpp:64
boost::shared_ptr< InputModule > InputModuleSharedPtr
void Stop()
Definition: Timer.cpp:62
double NekDouble
bool ModuleExists(tKey idKey)
Checks if a particular module is available.
Definition: NekFactory.hpp:229
boost::shared_ptr< Module > ModuleSharedPtr
void AddFile(string fileType, string fileName)
boost::shared_ptr< Field > FieldSharedPtr
Definition: Field.hpp:695
void Start()
Definition: Timer.cpp:51
NekDouble TimePerTest(unsigned int n)
Returns amount of seconds per iteration in a test with n iterations.
Definition: Timer.cpp:108
ModuleFactory & GetModuleFactory()
Abstract base class for input modules.
int main(int argc, char *argv[])