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  ("useSessionVariables",
89  "Use variables defined in session for output")
90  ("verbose,v",
91  "Enable verbose mode.");
92 
93  po::options_description hidden("Hidden options");
94  hidden.add_options()
95  ("input-file", po::value<vector<string> >(), "Input filename");
96 
97  po::options_description cmdline_options;
98  cmdline_options.add(hidden).add(desc);
99 
100  po::options_description visible("Allowed options");
101  visible.add(desc);
102 
103  po::positional_options_description p;
104  p.add("input-file", -1);
105 
106  po::variables_map vm;
107 
108  try
109  {
110  po::store(po::command_line_parser(argc, argv).
111  options(cmdline_options).positional(p).run(), vm);
112  po::notify(vm);
113  }
114  catch (const std::exception& e)
115  {
116  cerr << e.what() << endl;
117  cerr << desc;
118  return 1;
119  }
120 
121  // Print available modules.
122  if (vm.count("modules-list"))
123  {
125  return 1;
126  }
127 
128  if (vm.count("modules-opt"))
129  {
130  vector<string> tmp1;
131  boost::split(tmp1, vm["modules-opt"].as<string>(),
132  boost::is_any_of(":"));
133 
134  if (tmp1.size() != 2)
135  {
136  cerr << "ERROR: To specify a module, use one of in, out or proc "
137  << "together with the filename; for example in:vtk." << endl;
138  return 1;
139  }
140 
141  if (tmp1[0] != "in" && tmp1[0] != "out" && tmp1[0] != "proc")
142  {
143  cerr << "ERROR: Invalid module type " << tmp1[0] << endl;
144  return 1;
145  }
146 
147  ModuleType t;
148 
149  if (tmp1[0] == "in")
150  {
151  t = eInputModule;
152  }
153  else if (tmp1[0] == "out")
154  {
155  t = eOutputModule;
156  }
157  else if (tmp1[0] == "proc")
158  {
159  t = eProcessModule;
160  }
161 
162  FieldSharedPtr f = boost::shared_ptr<Field>(new Field());
164  ModuleKey(t, tmp1[1]), f);
165  cerr << "Options for module " << tmp1[1] << ":" << endl;
166  mod->PrintConfig();
167  return 1;
168  }
169 
170  if (vm.count("help") || vm.count("input-file") != 1) {
171  cerr << "Usage: FieldConvert [options] inputfile.ext1 outputfile.ext2"
172  << endl;
173  cout << desc;
174  cout << endl;
175  cout << "Example Usage: \n" << endl;
176  cout << "\t FieldConvert -m vorticity file.xml file.fld file_vort.fld "
177  << endl;
178  cout << "(This will add vorticity to file file.fld and put it in a "
179  "new file file_vort.fld) " << endl;
180  cout << endl;
181  cout << "\t FieldConvert file.xml file_vort.fld file_vort.dat " << endl;
182  cout << "(process file_vort.fld and make a tecplot output "
183  "file_vort.dat) " << endl;
184 
185  return 1;
186  }
187 
188  ASSERTL0(vm.count("input-file"),
189  "Must specify input(s) and/or output file.");
190  vector<string> inout = vm["input-file"].as<vector<string> >();
191 
192 
193  /*
194  * Process list of modules. Each element of the vector of module
195  * strings can be in the following form:
196  *
197  * modname:arg1=a:arg2=b:arg3=c:arg4:arg5=asd
198  *
199  * where the only required argument is 'modname', specifing the
200  * name of the module to load.
201  */
202 
203  FieldSharedPtr f = boost::shared_ptr<Field>(new Field());
204  if (LibUtilities::GetCommFactory().ModuleExists("ParallelMPI"))
205  {
206  if(vm.count("procid"))
207  {
208  int nprocs, rank;
209 
210  ASSERTL0(vm.count("nprocs"),
211  "Must specify --nprocs when using --procid option");
212  nprocs = vm["nprocs"].as<int>();
213  rank = vm["procid"].as<int>();
214 
215  f->m_comm = boost::shared_ptr<FieldConvertComm>(
216  new FieldConvertComm(argc, argv, nprocs,rank));
217 
218  // Set forceoutput option. Otherwise only procid 0 will write file
219  vm.insert(std::make_pair("forceoutput", po::variable_value()));
220  }
221  else
222  {
224  "ParallelMPI", argc, argv);
225  }
226  }
227  else
228  {
230  "Serial", argc, argv);
231 
232  }
233 
234  vector<ModuleSharedPtr> modules;
235  vector<string> modcmds;
236 
237 
238  if (vm.count("verbose"))
239  {
240  f->m_verbose = true;
241  }
242 
243  if (vm.count("module"))
244  {
245  modcmds = vm["module"].as<vector<string> >();
246  }
247 
248  // Add input and output modules to beginning and end of this vector.
249  modcmds.insert(modcmds.begin(), inout.begin(), inout.end()-1);
250  modcmds.push_back(*(inout.end()-1));
251 
252  int nInput = inout.size()-1;
253 
254  // For special case of part-only or part-only-overlapping options
255  // only require a single input file and so reset the nInputs to be
256  // of size inout.size(). Since the code will exit before reaching
257  // any output module this seems to work as expected
258  if(vm.count("part-only")||vm.count("part-only-overlapping"))
259  {
260  nInput = inout.size();
261  }
262 
263  InputModuleSharedPtr inputModule;
264 
265  for (int i = 0; i < modcmds.size(); ++i)
266  {
267  // First split each command by the colon separator.
268  vector<string> tmp1;
269  ModuleKey module;
270  int offset = 1;
271 
272  boost::split(tmp1, modcmds[i], boost::is_any_of(":"));
273 
274  if (i < nInput || i == modcmds.size() - 1)
275  {
276  module.first = (i < nInput ? eInputModule : eOutputModule);
277 
278  // If no colon detected, automatically detect mesh type from
279  // file extension. Otherwise override and use tmp1[1] as the
280  // module to load. This also allows us to pass options to
281  // input/output modules. So, for example, to override
282  // filename.xml to be read as vtk, you use:
283  //
284  // filename.xml:vtk:opt1=arg1:opt2=arg2
285  if (tmp1.size() == 1)
286  {
287  int dot = tmp1[0].find_last_of('.') + 1;
288  string ext = tmp1[0].substr(dot, tmp1[0].length() - dot);
289 
290  if(ext == "gz")
291  {
292  string tmp2 = tmp1[0].substr(0,dot-1);
293  dot = tmp2.find_last_of('.') + 1;
294  ext = tmp1[0].substr(dot,tmp1[0].length()-dot);
295  }
296 
297  module.second = ext;
298  tmp1.push_back(string(i < nInput ? "infile=" : "outfile=")
299  +tmp1[0]);
300  }
301  else
302  {
303  module.second = tmp1[1];
304  tmp1.push_back(string(i < nInput ? "infile=" : "outfile=")
305  +tmp1[0]);
306  offset++;
307  }
308  }
309  else
310  {
311  module.first = eProcessModule;
312  module.second = tmp1[0];
313  }
314 
315  // Create module.
316  ModuleSharedPtr mod;
317  mod = GetModuleFactory().CreateInstance(module, f);
318  modules.push_back(mod);
319 
320  if (i < nInput)
321  {
322  inputModule = boost::dynamic_pointer_cast<InputModule>(mod);
323  inputModule->AddFile(module.second, tmp1[0]);
324  }
325 
326  // Set options for this module.
327  for (int j = offset; j < tmp1.size(); ++j)
328  {
329  vector<string> tmp2;
330  boost::split(tmp2, tmp1[j], boost::is_any_of("="));
331 
332  if (tmp2.size() == 1)
333  {
334  mod->RegisterConfig(tmp2[0], "1");
335  }
336  else if (tmp2.size() == 2)
337  {
338  mod->RegisterConfig(tmp2[0], tmp2[1]);
339  }
340  else
341  {
342  cerr << "ERROR: Invalid module configuration: format is "
343  << "either :arg or :arg=val" << endl;
344  abort();
345  }
346  }
347 
348  // Ensure configuration options have been set.
349  mod->SetDefaults();
350  }
351 
352  // If any output module has to reset points then set intput modules to match
353  if(vm.count("noequispaced"))
354  {
355  for (int i = 0; i < modules.size(); ++i)
356  {
357  modules[i]->SetRequireEquiSpaced(false);
358  }
359  }
360  else
361  {
362  bool RequiresEquiSpaced = false;
363  for (int i = 0; i < modules.size(); ++i)
364  {
365  if(modules[i]->GetRequireEquiSpaced())
366  {
367  RequiresEquiSpaced = true;
368  }
369  }
370  if (RequiresEquiSpaced)
371  {
372  for (int i = 0; i < modules.size(); ++i)
373  {
374  modules[i]->SetRequireEquiSpaced(true);
375  }
376  }
377  }
378 
379  // Run field process.
380  for (int i = 0; i < modules.size(); ++i)
381  {
382  if(f->m_verbose && f->m_comm->TreatAsRankZero())
383  {
384  moduleTimer.Start();
385  }
386  modules[i]->Process(vm);
387  cout.flush();
388  if(f->m_verbose && f->m_comm->TreatAsRankZero())
389  {
390  moduleTimer.Stop();
391  NekDouble cpuTime = moduleTimer.TimePerTest(1);
392 
393  stringstream ss;
394  ss << cpuTime << "s";
395  cout << modules[i]->GetModuleName()
396  << " CPU Time: " << setw(8) << left
397  << ss.str() << endl;
398  }
399  }
400 
401  if(f->m_verbose)
402  {
403  if(f->m_comm->TreatAsRankZero())
404  {
405  timer.Stop();
406  NekDouble cpuTime = timer.TimePerTest(1);
407 
408  stringstream ss;
409  ss << cpuTime << "s";
410  cout << "Total CPU Time: " << setw(8) << left
411  << ss.str() << endl;
412  }
413  }
414  return 0;
415 }
#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:698
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[])