38#include <boost/algorithm/string.hpp>
39#include <boost/program_options.hpp>
52int main(
int argc,
char *argv[])
57 po::options_description desc(
"Available options");
58 po::options_description dep(
"Deprecated 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 "
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.");
100 po::options_description hidden(
"Hidden options");
101 hidden.add_options()(
"input-file", po::value<vector<string>>(),
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"}};
112 for (
auto &
d : deprecated)
114 std::string
description =
"Deprecated: use --" +
d.second;
115 dep.add_options()(
d.first.c_str(),
description.c_str());
118 po::options_description cmdline_options;
119 cmdline_options.add(hidden).add(desc).add(dep);
121 po::positional_options_description
p;
122 p.add(
"input-file", -1);
124 po::variables_map vm;
128 po::store(po::command_line_parser(argc, argv)
129 .options(cmdline_options)
135 catch (
const std::exception &e)
137 cerr << e.what() << endl;
144 if (std::getenv(
"NEKTAR_DISABLE_BACKUPS") !=
nullptr)
146 vm.insert(std::make_pair(
"force-output", po::variable_value()));
150 for (
auto &
d : deprecated)
152 if (vm.count(
d.first))
154 std::cerr <<
"WARNING: --" <<
d.first <<
" deprecated: use --"
155 <<
d.second << std::endl;
156 vm.emplace(
d.second, po::variable_value(vm[
d.first]));
161 if (vm.count(
"modules-list"))
167 if (vm.count(
"modules-opt"))
170 boost::split(tmp1, vm[
"modules-opt"].as<string>(),
171 boost::is_any_of(
":"));
173 if (tmp1.size() != 2)
175 cerr <<
"ERROR: To specify a module, use one of in, out or proc "
176 <<
"together with the filename; for example in:vtk." << endl;
180 if (tmp1[0] !=
"in" && tmp1[0] !=
"out" && tmp1[0] !=
"proc")
182 cerr <<
"ERROR: Invalid module type (in, out, or proc): " << tmp1[0]
193 else if (tmp1[0] ==
"out")
197 else if (tmp1[0] ==
"proc")
205 cerr <<
"Options for module " << tmp1[1] <<
":" << endl;
211 if (vm.count(
"help") || vm.count(
"input-file") != 1)
213 cerr <<
"Usage: FieldConvert [options] "
214 "[inputfile.xml] inputfile.ext1 outputfile.ext2"
218 cout <<
"Example Usage: \n" << endl;
219 cout <<
"\t FieldConvert -m vorticity file.xml file.fld file_vort.fld "
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.) "
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.) "
236 "Must specify input(s) and/or output file.");
237 vector<string> inout = vm[
"input-file"].as<vector<string>>();
260 if (vm.count(
"nparts"))
263 MPInprocs = MPIComm->GetSpaceComm()->GetSize();
264 MPIrank = MPIComm->GetSpaceComm()->GetRank();
266 nParts = vm[
"nparts"].as<
int>();
269 "Serial", argc, argv);
278 if (vm.count(
"nparts"))
280 nParts = vm[
"nparts"].as<
int>();
290 for (
auto io = inout.end() - 2; io != inout.end(); io++)
294 boost::split(tmp, *io, boost::is_any_of(
":"));
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();
303 auto start = filename.find_last_of(
"_") + 1;
304 auto index = atoi(filename.substr(start, filename.size()).c_str());
307 if (dir !=
"" && f->m_comm->TreatAsRankZero() &&
308 !fs::is_directory(dir) && io == inout.end() - 1)
310 fs::create_directory(dir);
315 auto index_new = index + f->m_comm->GetRank() % vm[
"npt"].as<
int>();
316 fs::path path_new = dir;
318 filename.substr(0, start) + std::to_string(index_new) + ftype;
322 *io = path_new.string();
323 for (
auto i = 1; i < tmp.size(); i++)
330 vector<ModuleSharedPtr> modules;
331 vector<string> modcmds;
335 if (vm.count(
"verbose"))
340 if (vm.count(
"module"))
342 modcmds = vm[
"module"].as<vector<string>>();
346 modcmds.insert(modcmds.begin(), inout.begin(), inout.end() - 1);
347 modcmds.push_back(inout.back());
349 int nInput = inout.size() - 1;
355 if (vm.count(
"part-only") || vm.count(
"part-only-overlapping"))
357 nInput = inout.size();
363 for (
int i = 0; i < modcmds.size(); ++i)
369 boost::split(tmp1, modcmds[i], boost::is_any_of(
":"));
371 if (i < nInput || i == modcmds.size() - 1)
375 if (tmp1.size() > 1 && tmp1.back() ==
"out")
388 if (tmp1.size() == 1)
396 guess = InputModule::GuessFormat(tmp1[0]);
404 cout <<
"Using input module " << guess
405 <<
" for: " << tmp1[0] << endl;
408 module.second = guess;
409 tmp1.push_back(
string(
"infile=" + tmp1[0]));
413 int dot = tmp1[0].find_last_of(
'.') + 1;
414 string ext = tmp1[0].substr(dot, tmp1[0].length() - dot);
418 if (ext.back() == fs::path::preferred_separator)
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);
439 module.second = tmp1[1];
450 module.second = tmp1[0];
455 modules.push_back(mod);
459 inputModule = std::dynamic_pointer_cast<InputModule>(mod);
460 inputModule->AddFile(module.second, tmp1[0]);
464 outfilename = tmp1[0];
469 mod->RegisterConfig(
"writemultiplefiles");
474 for (
int j = offset; j < tmp1.size(); ++j)
477 boost::split(tmp2, tmp1[j], boost::is_any_of(
"="));
479 if (tmp2.size() == 1)
481 mod->RegisterConfig(tmp2[0]);
483 else if (tmp2.size() == 2)
485 mod->RegisterConfig(tmp2[0], tmp2[1]);
489 cerr <<
"ERROR: Invalid module configuration: format is "
490 <<
"either :arg or :arg=val" << endl;
500 for (
int i = 0; i < modules.size(); ++i)
502 ++modulesCount[modules[i]->GetModulePriority()];
506 for (
int i = 0; i < modules.size(); ++i)
509 for (
int j = 0; j < modules[i]->GetModulePrerequisites().size(); ++j)
512 modules[i]->GetModulePrerequisites()[j], f);
514 if (modulesCount[mod->GetModulePriority()] == 0)
516 ++modulesCount[mod->GetModulePriority()];
517 modules.push_back(mod);
528 module.second = string(
"equispacedoutput");
530 modules.push_back(mod);
537 if (vm.count(
"range") && f->m_declareExpansionAsContField)
539 ASSERTL0(
false,
"Can't use range option with module requiring "
540 "a continuous expansion.");
543 bool verbose = (f->m_verbose && f->m_comm->TreatAsRankZero());
552 for (
int p = MPIrank;
p < nParts;
p += MPInprocs)
558 cout << endl <<
"Processing partition: " <<
p << endl;
562 partComm = std::shared_ptr<FieldConvertComm>(
575 f->m_comm = partComm;
583 for (
int i = 0; i < modules.size(); ++i)
585 if (modules[i]->GetModulePriority() == priority)
598 for (i = 0; i < modules.size(); ++i)
600 if (boost::iequals(modules[i]->GetModuleName(),
"OutputFld"))
606 if (i != modules.size())
610 MPIComm->GetSpaceComm()->Block();
616 module.second = string(
"info");
619 mod->RegisterConfig(
"nparts",
620 boost::lexical_cast<string>(nParts));
623 if (f->m_writeBndFld)
626 int dot = outfilename.find_last_of(
'.') + 1;
628 outfilename.substr(dot, outfilename.length() - dot);
629 string name = outfilename.substr(0, dot - 1);
631 for (
int b = 0; b < f->m_bndRegionsToWrite.size(); ++b)
633 string outfilenew =
name +
"_b" +
634 boost::lexical_cast<string>(
635 f->m_bndRegionsToWrite[b]) +
637 mod->RegisterConfig(
"outfile", outfilenew);
643 mod->RegisterConfig(
"outfile", outfilename);
657 ss << cpuTime <<
"s";
658 cout <<
"Total CPU Time: " << setw(8) << left << ss.str() << endl;
663 MPIComm->GetSpaceComm()->Block();
664 MPIComm->GetSpaceComm()->Finalise();
675 for (
int i = 0; i < modules.size(); ++i)
677 ++modulesCount[modules[i]->GetModulePriority()];
686 for (
int i = 0; i < modules.size(); ++i)
690 ss << modules[i]->GetModuleName() <<
" ";
693 ss <<
"require fld input.";
705 for (
int i = 0; i < modules.size(); ++i)
707 if (modules[i]->GetModulePriority() ==
eFillExp)
709 ss << modules[i]->GetModuleName() <<
" ";
712 ss <<
"require xml input without fld input.";
724 for (
int i = 0; i < modules.size(); ++i)
726 if (modules[i]->GetModulePriority() ==
eModifyExp ||
729 ss << modules[i]->GetModuleName() <<
" ";
732 ss <<
"require xml input.";
744 for (
int i = 0; i < modules.size(); ++i)
746 if (modules[i]->GetModulePriority() ==
eCreatePts)
748 ss << modules[i]->GetModuleName() <<
" ";
751 ss <<
"should not use xml or fld inputs.";
764 for (
int i = 0; i < modules.size(); ++i)
768 ss << modules[i]->GetModuleName() <<
" ";
771 ss <<
"require xml input.";
778 for (
int i = 0; i < modules.size(); ++i)
782 ss << modules[i]->GetModuleName() <<
" ";
785 ss <<
"is not compatible with module(s): ";
786 for (
int i = 0; i < modules.size(); ++i)
790 ss << modules[i]->GetModuleName() <<
" ";
803 cout <<
"Execution sequence:" << endl;
807 for (
int i = 0; i < modules.size(); ++i)
809 if (modules[i]->GetModulePriority() == priority)
813 cout <<
"\t" << modules[i]->GetModuleName();
818 cout <<
" -> " << modules[i]->GetModuleName();
834 cout << module->GetModuleName() <<
": "
835 << module->GetModuleDescription() << endl;
845 ss << cpuTime <<
"s";
846 cout << module->GetModuleName() <<
" CPU Time: " << setw(8) << left
#define ASSERTL0(condition, msg)
int main(int argc, char *argv[])
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)