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