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::Utilities;
43 
44 int main(int argc, char* argv[])
45 {
46  Timer timer;
47  timer.Start();
48  po::options_description desc("Available options");
49  desc.add_options()
50  ("help,h",
51  "Produce this help message.")
52  ("modules-list,l",
53  "Print the list of available modules.")
54  ("output-points,n", po::value<int>(),
55  "Output at n equipspaced points along the collapsed coordinates (for .dat, .vtk).")
56  ("output-points-hom-z", po::value<int>(),
57  "Number of planes in the z-direction for output of Homogeneous 1D expansion(for .dat, .vtk).")
58  ("error,e",
59  "Write error of fields for regression checking")
60  ("forceoutput,f",
61  "Force the output to be written without any checks")
62  ("range,r", po::value<string>(),
63  "Define output range i.e. (-r xmin,xmax,ymin,ymax,zmin,zmax) "
64  "in which any vertex is contained.")
65  ("noequispaced","Do not use equispaced output. Currently stops the output-points option")
66  ("nprocs", po::value<int>(),
67  "Used to define nprocs if running serial problem to mimic "
68  "parallel run.")
69  ("onlyshape", po::value<string>(),
70  "Only use element with defined shape type i.e. -onlyshape "
71  " Tetrahedron")
72  ("part-only", po::value<int>(),
73  "Partition into specfiied npart partitions and exit")
74  ("part-only-overlapping", po::value<int>(),
75  "Partition into specfiied npart overlapping partitions and exit")
76  ("procid", po::value<int>(),
77  "Process as single procid of a partition of size nproc "
78  "(-nproc must be specified).")
79  ("modules-opt,p", po::value<string>(),
80  "Print options for a module.")
81  ("module,m", po::value<vector<string> >(),
82  "Specify modules which are to be used.")
83  ("shared-filesystem,s", "Using shared filesystem.")
84  ("useSessionVariables",
85  "Use variables defined in session for output")
86  ("verbose,v",
87  "Enable verbose mode.");
88 
89  po::options_description hidden("Hidden options");
90  hidden.add_options()
91  ("input-file", po::value<vector<string> >(), "Input filename");
92 
93  po::options_description cmdline_options;
94  cmdline_options.add(hidden).add(desc);
95 
96  po::options_description visible("Allowed options");
97  visible.add(desc);
98 
99  po::positional_options_description p;
100  p.add("input-file", -1);
101 
102  po::variables_map vm;
103 
104  try
105  {
106  po::store(po::command_line_parser(argc, argv).
107  options(cmdline_options).positional(p).run(), vm);
108  po::notify(vm);
109  }
110  catch (const std::exception& e)
111  {
112  cerr << e.what() << endl;
113  cerr << desc;
114  return 1;
115  }
116 
117  // Print available modules.
118  if (vm.count("modules-list"))
119  {
121  return 1;
122  }
123 
124  if (vm.count("modules-opt"))
125  {
126  vector<string> tmp1;
127  boost::split(tmp1, vm["modules-opt"].as<string>(),
128  boost::is_any_of(":"));
129 
130  if (tmp1.size() != 2)
131  {
132  cerr << "ERROR: To specify a module, use one of in, out or proc "
133  << "together with the filename; for example in:vtk." << endl;
134  return 1;
135  }
136 
137  if (tmp1[0] != "in" && tmp1[0] != "out" && tmp1[0] != "proc")
138  {
139  cerr << "ERROR: Invalid module type " << tmp1[0] << endl;
140  return 1;
141  }
142 
143  ModuleType t;
144 
145  if (tmp1[0] == "in")
146  {
147  t = eInputModule;
148  }
149  else if (tmp1[0] == "out")
150  {
151  t = eOutputModule;
152  }
153  else if (tmp1[0] == "proc")
154  {
155  t = eProcessModule;
156  }
157 
158  FieldSharedPtr f = boost::shared_ptr<Field>(new Field());
160  ModuleKey(t, tmp1[1]), f);
161  cerr << "Options for module " << tmp1[1] << ":" << endl;
162  mod->PrintConfig();
163  return 1;
164  }
165 
166  if (vm.count("help") || vm.count("input-file") != 1) {
167  cerr << "Usage: FieldConvert [options] inputfile.ext1 outputfile.ext2"
168  << endl;
169  cout << desc;
170  cout << endl;
171  cout << "Example Usage: \n" << endl;
172  cout << "\t FieldConvert -m vorticity file.xml file.fld file_vort.fld "
173  << endl;
174  cout << "(This will add vorticity to file file.fld and put it in a "
175  "new file file_vort.fld) " << endl;
176  cout << endl;
177  cout << "\t FieldConvert file.xml file_vort.fld file_vort.dat " << endl;
178  cout << "(process file_vort.fld and make a tecplot output "
179  "file_vort.dat) " << endl;
180 
181  return 1;
182  }
183 
184  ASSERTL0(vm.count("input-file"),
185  "Must specify input(s) and/or output file.");
186  vector<string> inout = vm["input-file"].as<vector<string> >();
187 
188 
189  /*
190  * Process list of modules. Each element of the vector of module
191  * strings can be in the following form:
192  *
193  * modname:arg1=a:arg2=b:arg3=c:arg4:arg5=asd
194  *
195  * where the only required argument is 'modname', specifing the
196  * name of the module to load.
197  */
198 
199  FieldSharedPtr f = boost::shared_ptr<Field>(new Field());
200  if (LibUtilities::GetCommFactory().ModuleExists("ParallelMPI"))
201  {
202  if(vm.count("procid"))
203  {
204  int nprocs, rank;
205 
206  ASSERTL0(vm.count("nprocs"),
207  "Must specify --nprocs when using --procid option");
208  nprocs = vm["nprocs"].as<int>();
209  rank = vm["procid"].as<int>();
210 
211  f->m_comm = boost::shared_ptr<FieldConvertComm>(
212  new FieldConvertComm(argc, argv, nprocs,rank));
213  }
214  else
215  {
217  "ParallelMPI", argc, argv);
218  }
219  }
220  else
221  {
223  "Serial", argc, argv);
224 
225  }
226 
227  vector<ModuleSharedPtr> modules;
228  vector<string> modcmds;
229 
230 
231  if (vm.count("verbose"))
232  {
233  f->m_verbose = true;
234  }
235 
236  if (vm.count("module"))
237  {
238  modcmds = vm["module"].as<vector<string> >();
239  }
240 
241  // Add input and output modules to beginning and end of this vector.
242  modcmds.insert(modcmds.begin(), inout.begin(), inout.end()-1);
243  modcmds.push_back(*(inout.end()-1));
244 
245  int nInput = inout.size()-1;
246 
247  // For special case of part-only or part-only-overlapping options
248  // only require a single input file and so reset the nInputs to be
249  // of size inout.size(). Since the code will exit before reaching
250  // any output module this seems to work as expected
251  if(vm.count("part-only")||vm.count("part-only-overlapping"))
252  {
253  nInput = inout.size();
254  }
255 
256  InputModuleSharedPtr inputModule;
257 
258  for (int i = 0; i < modcmds.size(); ++i)
259  {
260  // First split each command by the colon separator.
261  vector<string> tmp1;
262  ModuleKey module;
263  int offset = 1;
264 
265  boost::split(tmp1, modcmds[i], boost::is_any_of(":"));
266 
267  if (i < nInput || i == modcmds.size() - 1)
268  {
269  module.first = (i < nInput ? eInputModule : eOutputModule);
270 
271  // If no colon detected, automatically detect mesh type from
272  // file extension. Otherwise override and use tmp1[1] as the
273  // module to load. This also allows us to pass options to
274  // input/output modules. So, for example, to override
275  // filename.xml to be read as vtk, you use:
276  //
277  // filename.xml:vtk:opt1=arg1:opt2=arg2
278  if (tmp1.size() == 1)
279  {
280  int dot = tmp1[0].find_last_of('.') + 1;
281  string ext = tmp1[0].substr(dot, tmp1[0].length() - dot);
282 
283  if(ext == "gz")
284  {
285  string tmp2 = tmp1[0].substr(0,dot-1);
286  dot = tmp2.find_last_of('.') + 1;
287  ext = tmp1[0].substr(dot,tmp1[0].length()-dot);
288  }
289 
290  module.second = ext;
291  tmp1.push_back(string(i < nInput ? "infile=" : "outfile=")
292  +tmp1[0]);
293  }
294  else
295  {
296  module.second = tmp1[1];
297  tmp1.push_back(string(i < nInput ? "infile=" : "outfile=")
298  +tmp1[0]);
299  offset++;
300  }
301  }
302  else
303  {
304  module.first = eProcessModule;
305  module.second = tmp1[0];
306  }
307 
308  // Create module.
309  ModuleSharedPtr mod;
310  mod = GetModuleFactory().CreateInstance(module, f);
311  modules.push_back(mod);
312 
313  if (i < nInput)
314  {
315  inputModule = boost::dynamic_pointer_cast<InputModule>(mod);
316  inputModule->AddFile(module.second, tmp1[0]);
317  }
318 
319  // Set options for this module.
320  for (int j = offset; j < tmp1.size(); ++j)
321  {
322  vector<string> tmp2;
323  boost::split(tmp2, tmp1[j], boost::is_any_of("="));
324 
325  if (tmp2.size() == 1)
326  {
327  mod->RegisterConfig(tmp2[0], "1");
328  }
329  else if (tmp2.size() == 2)
330  {
331  mod->RegisterConfig(tmp2[0], tmp2[1]);
332  }
333  else
334  {
335  cerr << "ERROR: Invalid module configuration: format is "
336  << "either :arg or :arg=val" << endl;
337  abort();
338  }
339  }
340 
341  // Ensure configuration options have been set.
342  mod->SetDefaults();
343  }
344 
345  // If any output module has to reset points then set intput modules to match
346  if(vm.count("noequispaced"))
347  {
348  for (int i = 0; i < modules.size(); ++i)
349  {
350  modules[i]->SetRequireEquiSpaced(false);
351  }
352  }
353  else
354  {
355  bool RequiresEquiSpaced = false;
356  for (int i = 0; i < modules.size(); ++i)
357  {
358  if(modules[i]->GetRequireEquiSpaced())
359  {
360  RequiresEquiSpaced = true;
361  }
362  }
363  if (RequiresEquiSpaced)
364  {
365  for (int i = 0; i < modules.size(); ++i)
366  {
367  modules[i]->SetRequireEquiSpaced(true);
368  }
369  }
370  }
371 
372  // Run field process.
373  for (int i = 0; i < modules.size(); ++i)
374  {
375  modules[i]->Process(vm);
376  cout.flush();
377  }
378 
379  if(f->m_verbose)
380  {
381  if(f->m_comm->GetRank() == 0)
382  {
383  timer.Stop();
384  NekDouble cpuTime = timer.TimePerTest(1);
385 
386  stringstream ss;
387  ss << cpuTime << "s";
388  cout << "Total CPU Time: " << setw(8) << left
389  << ss.str() << endl;
390  cpuTime = 0.0;
391  }
392 
393  }
394  return 0;
395 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:161
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[])