53{
56
57 po::options_description desc("Available options");
58 po::options_description dep("Deprecated options");
59
60
61 desc.add_options()
62 ("help,h", "Produce this help message.")
63 ("modules-list,l", "Print the list of available modules.")
64 ("output-points,n", po::value<int>(),
65 "Output at n equipspaced points along the "
66 "collapsed coordinates (for .dat, .vtu).")
67 ("output-points-hom-z", po::value<int>(),
68 "Number of planes in the z-direction for output of "
69 "Homogeneous 1D expansion(for .dat, .vtu).")
70 ("error,e", "Write error of fields for regression checking")
71 ("force-output,f", "Force the output to be written without any checks")
72 ("range,r", po::value<string>(),
73 "Define output range i.e. (-r xmin,xmax,ymin,ymax,zmin,zmax) "
74 "in which any vertex is contained.")
75 ("no-equispaced", "Do not use equispaced output.")
76 ("nparts", po::value<int>(),
77 "Define nparts if running serial problem to mimic "
78 "parallel run with many partitions.")
79 ("npz", po::value<int>(),
80 "Used to define number of partitions in z for Homogeneous1D "
81 "expansions for parallel runs.")
82 ("npt", po::value<int>(),
83 "Used to define number of partitions in time for Parareal runs. ")
84 ("onlyshape", po::value<string>(),
85 "Only use element with defined shape type i.e. -onlyshape "
86 " Tetrahedron")
87 ("part-only", po::value<int>(),
88 "Partition into specified npart partitions and exit")
89 ("part-only-overlapping", po::value<int>(),
90 "Partition into specified npart overlapping partitions and exit")
91 ("modules-opt,p", po::value<string>(),
92 "Print options for a module.")
93 ("module,m", po::value<vector<string>>(),
94 "Specify modules which are to be used.")
95 ("use-session-variables", "Use variables defined in session for output")
96 ("use-session-expansion", "Use expansion defined in session.")
97 ("verbose,v", "Enable verbose mode.");
98
99
100 po::options_description hidden("Hidden options");
101 hidden.add_options()("input-file", po::value<vector<string>>(),
102 "Input filename");
103
104
105
106 std::map<std::string, std::string> deprecated = {
107 {"forceoutput", "force-output"},
108 {"noequispaced", "no-equispaced"},
109 {"useSessionVariables", "use-session-variables"},
110 {"useSessionExpansion", "use-session-expansion"}};
111
112 for (
auto &
d : deprecated)
113 {
114 std::string
description =
"Deprecated: use --" +
d.second;
115 dep.add_options()(
d.first.c_str(),
description.c_str());
116 }
117
118 po::options_description cmdline_options;
119 cmdline_options.add(hidden).add(desc).add(dep);
120
121 po::positional_options_description
p;
122 p.add(
"input-file", -1);
123
124 po::variables_map vm;
125
126 try
127 {
128 po::store(po::command_line_parser(argc, argv)
129 .options(cmdline_options)
132 vm);
133 po::notify(vm);
134 }
135 catch (const std::exception &e)
136 {
137 cerr << e.what() << endl;
138 cerr << desc;
139 return 1;
140 }
141
142
143
144 if (std::getenv("NEKTAR_DISABLE_BACKUPS") != nullptr)
145 {
146 vm.insert(std::make_pair("force-output", po::variable_value()));
147 }
148
149
150 for (
auto &
d : deprecated)
151 {
152 if (vm.count(
d.first))
153 {
154 std::cerr <<
"WARNING: --" <<
d.first <<
" deprecated: use --"
155 <<
d.second << std::endl;
156 vm.emplace(
d.second, po::variable_value(vm[
d.first]));
157 }
158 }
159
160
161 if (vm.count("modules-list"))
162 {
164 return 1;
165 }
166
167 if (vm.count("modules-opt"))
168 {
169 vector<string> tmp1;
170 boost::split(tmp1, vm["modules-opt"].as<string>(),
171 boost::is_any_of(":"));
172
173 if (tmp1.size() != 2)
174 {
175 cerr << "ERROR: To specify a module, use one of in, out or proc "
176 << "together with the filename; for example in:vtk." << endl;
177 return 1;
178 }
179
180 if (tmp1[0] != "in" && tmp1[0] != "out" && tmp1[0] != "proc")
181 {
182 cerr << "ERROR: Invalid module type (in, out, or proc): " << tmp1[0]
183 << endl;
184 return 1;
185 }
186
188
189 if (tmp1[0] == "in")
190 {
192 }
193 else if (tmp1[0] == "out")
194 {
196 }
197 else if (tmp1[0] == "proc")
198 {
200 }
201
205 cerr << "Options for module " << tmp1[1] << ":" << endl;
206 mod->PrintConfig();
207 return 1;
208 }
209
210
211 if (vm.count("help") || vm.count("input-file") != 1)
212 {
213 cerr << "Usage: FieldConvert [options] "
214 "[inputfile.xml] inputfile.ext1 outputfile.ext2"
215 << endl;
216 cout << desc;
217 cout << endl;
218 cout << "Example Usage: \n" << endl;
219 cout << "\t FieldConvert -m vorticity file.xml file.fld file_vort.fld "
220 << endl;
221 cout << "(This will add vorticity to file file.fld and put it in a "
222 "new file file_vort.fld. \n file.xml is a Nektar XML input "
223 "file containing the geometry.) "
224 << endl;
225 cout << endl;
226 cout << "\t FieldConvert file.xml file_vort.fld file_vort.dat " << endl;
227 cout << "(process file_vort.fld and make a tecplot output "
228 "file_vort.dat. file.xml is a\n Nektar XML input file "
229 "containing the geometry.) "
230 << endl;
231
232 return 1;
233 }
234
236 "Must specify input(s) and/or output file.");
237 vector<string> inout = vm["input-file"].as<vector<string>>();
238
239
240
241
242
243
244
245
246
247
249 int nParts = 1;
250 int MPInprocs = 1;
251 int MPIrank = 0;
253
255 {
256
258 argc, argv);
259
260 if (vm.count("nparts"))
261 {
262
263 MPInprocs = MPIComm->GetSpaceComm()->GetSize();
264 MPIrank = MPIComm->GetSpaceComm()->GetRank();
265
266 nParts = vm["nparts"].as<int>();
267
269 "Serial", argc, argv);
270 }
271 else
272 {
273 f->m_comm = MPIComm;
274 }
275 }
276 else
277 {
278 if (vm.count("nparts"))
279 {
280 nParts = vm["nparts"].as<int>();
281 }
282
283 f->m_comm =
285 }
286
287
288 if (vm.count("npt"))
289 {
290 for (auto io = inout.end() - 2; io != inout.end(); io++)
291 {
292
293 vector<string> tmp;
294 boost::split(tmp, *io, boost::is_any_of(":"));
295
296
297 fs::path path = tmp[0];
298 fs::path dir = path.parent_path();
299 string ftype = path.extension().string();
300 string filename = path.stem().string();
301
302
303 auto start = filename.find_last_of("_") + 1;
304 auto index = atoi(filename.substr(start, filename.size()).c_str());
305
306
307 if (dir != "" && f->m_comm->TreatAsRankZero() &&
308 !fs::is_directory(dir) && io == inout.end() - 1)
309 {
310 fs::create_directory(dir);
311 }
312
313
314
315 auto index_new = index + f->m_comm->GetRank() % vm["npt"].as<int>();
316 fs::path path_new = dir;
317 path_new /=
318 filename.substr(0, start) + std::to_string(index_new) + ftype;
319
320
321
322 *io = path_new.string();
323 for (auto i = 1; i < tmp.size(); i++)
324 {
325 *io += ":" + tmp[i];
326 }
327 }
328 }
329
330 vector<ModuleSharedPtr> modules;
331 vector<string> modcmds;
334
335 if (vm.count("verbose"))
336 {
337 f->m_verbose = true;
338 }
339
340 if (vm.count("module"))
341 {
342 modcmds = vm["module"].as<vector<string>>();
343 }
344
345
346 modcmds.insert(modcmds.begin(), inout.begin(), inout.end() - 1);
347 modcmds.push_back(inout.back());
348
349 int nInput = inout.size() - 1;
350
351
352
353
354
355 if (vm.count("part-only") || vm.count("part-only-overlapping"))
356 {
357 nInput = inout.size();
358 }
359
361 string outfilename;
362
363 for (int i = 0; i < modcmds.size(); ++i)
364 {
365
366 vector<string> tmp1;
367 int offset = 1;
368
369 boost::split(tmp1, modcmds[i], boost::is_any_of(":"));
370
371 if (i < nInput || i == modcmds.size() - 1)
372 {
373
375 if (tmp1.size() > 1 && tmp1.back() == "out")
376 {
378 tmp1.pop_back();
379 }
380
381
382
383
384
385
386
387
388 if (tmp1.size() == 1)
389 {
390
391
392 string guess;
393
395 {
396 guess = InputModule::GuessFormat(tmp1[0]);
397 }
398
399
400 if (guess != "")
401 {
402 if (f->m_verbose)
403 {
404 cout << "Using input module " << guess
405 << " for: " << tmp1[0] << endl;
406 }
407
408 module.second = guess;
409 tmp1.push_back(string("infile=" + tmp1[0]));
410 }
411 else
412 {
413 int dot = tmp1[0].find_last_of('.') + 1;
414 string ext = tmp1[0].substr(dot, tmp1[0].length() - dot);
415
416
417
418 if (ext.back() == fs::path::preferred_separator)
419 {
420 ext.pop_back();
421 }
422
423 if (ext == "gz")
424 {
425 string tmp2 = tmp1[0].substr(0, dot - 1);
426 dot = tmp2.find_last_of('.') + 1;
427 ext = tmp1[0].substr(dot, tmp1[0].length() - dot);
428 }
429
430 module.second = ext;
432 ? "infile="
433 : "outfile=") +
434 tmp1[0]);
435 }
436 }
437 else
438 {
439 module.second = tmp1[1];
441 ? "infile="
442 : "outfile=") +
443 tmp1[0]);
444 offset++;
445 }
446 }
447 else
448 {
450 module.second = tmp1[0];
451 }
452
453
455 modules.push_back(mod);
456
458 {
459 inputModule = std::dynamic_pointer_cast<InputModule>(mod);
460 inputModule->AddFile(module.second, tmp1[0]);
461 }
463 {
464 outfilename = tmp1[0];
465 if (nParts > 1)
466 {
467
468
469 mod->RegisterConfig("writemultiplefiles");
470 }
471 }
472
473
474 for (int j = offset; j < tmp1.size(); ++j)
475 {
476 vector<string> tmp2;
477 boost::split(tmp2, tmp1[j], boost::is_any_of("="));
478
479 if (tmp2.size() == 1)
480 {
481 mod->RegisterConfig(tmp2[0]);
482 }
483 else if (tmp2.size() == 2)
484 {
485 mod->RegisterConfig(tmp2[0], tmp2[1]);
486 }
487 else
488 {
489 cerr << "ERROR: Invalid module configuration: format is "
490 << "either :arg or :arg=val" << endl;
491 abort();
492 }
493 }
494
495
496 mod->SetDefaults();
497 }
498
500 for (int i = 0; i < modules.size(); ++i)
501 {
502 ++modulesCount[modules[i]->GetModulePriority()];
503 }
504
505
506 for (int i = 0; i < modules.size(); ++i)
507 {
508
509 for (int j = 0; j < modules[i]->GetModulePrerequisites().size(); ++j)
510 {
512 modules[i]->GetModulePrerequisites()[j], f);
513
514 if (modulesCount[mod->GetModulePriority()] == 0)
515 {
516 ++modulesCount[mod->GetModulePriority()];
517 modules.push_back(mod);
518 mod->SetDefaults();
519 }
520 }
521 }
522
523
526 {
528 module.second = string("equispacedoutput");
530 modules.push_back(mod);
531 mod->SetDefaults();
532 }
533
534
536
537 if (vm.count("range") && f->m_declareExpansionAsContField)
538 {
539 ASSERTL0(
false,
"Can't use range option with module requiring "
540 "a continuous expansion.");
541 }
542
543 bool verbose = (f->m_verbose && f->m_comm->TreatAsRankZero());
544 if (verbose)
545 {
547 }
548
549
552 for (
int p = MPIrank;
p < nParts;
p += MPInprocs)
553 {
554
555
556 if (nParts > 1)
557 {
558 cout << endl <<
"Processing partition: " <<
p << endl;
559
561 f->ClearField();
562 partComm = std::shared_ptr<FieldConvertComm>(
564 }
565
566
568 {
570
571 if (nParts > 1)
572 {
574 {
575 f->m_comm = partComm;
576 }
577 else
578 {
579 f->m_comm = defComm;
580 }
581 }
582
583 for (int i = 0; i < modules.size(); ++i)
584 {
585 if (modules[i]->GetModulePriority() == priority)
586 {
588 }
589 }
590 }
591 }
592
593
594 if (nParts > 1)
595 {
596 int i;
597
598 for (i = 0; i < modules.size(); ++i)
599 {
600 if (boost::iequals(modules[i]->GetModuleName(), "OutputFld"))
601 {
602 break;
603 }
604 }
605
606 if (i != modules.size())
607 {
608 if (MPInprocs > 1)
609 {
610 MPIComm->GetSpaceComm()->Block();
611 }
612
613 if (MPIrank == 0)
614 {
616 module.second = string("info");
618
619 mod->RegisterConfig("nparts",
620 boost::lexical_cast<string>(nParts));
621 mod->SetDefaults();
622
623 if (f->m_writeBndFld)
624 {
625
626 int dot = outfilename.find_last_of('.') + 1;
627 string ext =
628 outfilename.substr(dot, outfilename.length() - dot);
629 string name = outfilename.substr(0, dot - 1);
630
631 for (int b = 0; b < f->m_bndRegionsToWrite.size(); ++b)
632 {
633 string outfilenew =
name +
"_b" +
634 boost::lexical_cast<string>(
635 f->m_bndRegionsToWrite[b]) +
636 "." + ext;
637 mod->RegisterConfig("outfile", outfilenew);
639 }
640 }
641 else
642 {
643 mod->RegisterConfig("outfile", outfilename);
645 }
646 }
647 }
648 }
649
651
652 if (verbose)
653 {
655
656 stringstream ss;
657 ss << cpuTime << "s";
658 cout << "Total CPU Time: " << setw(8) << left << ss.str() << endl;
659 }
660
661 if (MPInprocs > 1)
662 {
663 MPIComm->GetSpaceComm()->Block();
664 MPIComm->GetSpaceComm()->Finalise();
665 }
666
667 return 0;
668}
void PrintExecutionSequence(vector< ModuleSharedPtr > &modules)
void RunModule(ModuleSharedPtr module, po::variables_map &vm, bool verbose)
void CheckModules(vector< ModuleSharedPtr > &modules)
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
void PrintAvailableClasses(std::ostream &pOut=std::cout)
Prints the available classes to stdout.
NekDouble TimePerTest(unsigned int n)
Returns amount of seconds per iteration in a test with n iterations.
def description(self, force=False, cellml=False)
std::shared_ptr< Field > FieldSharedPtr
std::pair< ModuleType, std::string > ModuleKey
std::shared_ptr< InputModule > InputModuleSharedPtr
std::shared_ptr< Module > ModuleSharedPtr
ModuleFactory & GetModuleFactory()
CommFactory & GetCommFactory()
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
std::vector< double > d(NPUPPER *NPUPPER)