Nektar++
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// Permission is hereby granted, free of charge, to any person obtaining a
14// copy of this software and associated documentation files (the "Software"),
15// to deal in the Software without restriction, including without limitation
16// the rights to use, copy, modify, merge, publish, distribute, sublicense,
17// and/or sell copies of the Software, and to permit persons to whom the
18// Software is furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included
21// in all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29// DEALINGS IN THE SOFTWARE.
30//
31// Description: Field conversion utility.
32//
33////////////////////////////////////////////////////////////////////////////////
34
35#include <FieldUtils/Module.h>
38#include <boost/algorithm/string.hpp>
39#include <boost/program_options.hpp>
40#include <string>
41
42using namespace std;
43using namespace Nektar;
44using namespace Nektar::FieldUtils;
45
46void CheckModules(vector<ModuleSharedPtr> &modules);
47
48void PrintExecutionSequence(vector<ModuleSharedPtr> &modules);
49
50void RunModule(ModuleSharedPtr module, po::variables_map &vm, bool verbose);
51
52int main(int argc, char *argv[])
53{
55 timer.Start();
56
57 po::options_description desc("Available options");
58 po::options_description dep("Deprecated options");
59
60 // clang-format off
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 // clang-format on
99
100 po::options_description hidden("Hidden options");
101 hidden.add_options()("input-file", po::value<vector<string>>(),
102 "Input filename");
103
104 // Deprecated options: introduced in 5.4.0 to homogenise command-line
105 // options to use '-' instead of camelCase or no spaces.
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)
130 .positional(p)
131 .run(),
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 // If NEKTAR_DISABLE_BACKUPS environment variable is set, enable the
143 // force-output option.
144 if (std::getenv("NEKTAR_DISABLE_BACKUPS") != nullptr)
145 {
146 vm.insert(std::make_pair("force-output", po::variable_value()));
147 }
148
149 // Deal with deprecated options.
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 // Print available modules.
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 {
191 t = eInputModule;
192 }
193 else if (tmp1[0] == "out")
194 {
195 t = eOutputModule;
196 }
197 else if (tmp1[0] == "proc")
198 {
199 t = eProcessModule;
200 }
201
202 FieldSharedPtr f = std::shared_ptr<Field>(new Field());
203 ModuleSharedPtr mod =
204 GetModuleFactory().CreateInstance(ModuleKey(t, tmp1[1]), f);
205 cerr << "Options for module " << tmp1[1] << ":" << endl;
206 mod->PrintConfig();
207 return 1;
208 }
209
210 // Print help message.
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
235 ASSERTL0(vm.count("input-file"),
236 "Must specify input(s) and/or output file.");
237 vector<string> inout = vm["input-file"].as<vector<string>>();
238
239 /*
240 * Process list of modules. Each element of the vector of module
241 * strings can be in the following form:
242 *
243 * modname:arg1=a:arg2=b:arg3=c:arg4:arg5=asd
244 *
245 * where the only required argument is 'modname', specifing the
246 * name of the module to load.
247 */
248 FieldSharedPtr f = std::shared_ptr<Field>(new Field());
249 int nParts = 1;
250 int MPInprocs = 1;
251 int MPIrank = 0;
253
254 if (LibUtilities::GetCommFactory().ModuleExists("ParallelMPI"))
255 {
256 // Get hold of parallel communicator first.
257 MPIComm = LibUtilities::GetCommFactory().CreateInstance("ParallelMPI",
258 argc, argv);
259
260 if (vm.count("nparts"))
261 {
262 // Work out number of processors to run in serial over partitions.
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 =
284 LibUtilities::GetCommFactory().CreateInstance("Serial", argc, argv);
285 }
286
287 // For parallel-in-time.
288 if (vm.count("npt"))
289 {
290 for (auto io = inout.end() - 2; io != inout.end(); io++)
291 {
292 // First split each command by the colon separator.
293 vector<string> tmp;
294 boost::split(tmp, *io, boost::is_any_of(":"));
295
296 // Get original filename and extension.
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 // Determine original index from filename.
303 auto start = filename.find_last_of("_") + 1;
304 auto index = atoi(filename.substr(start, filename.size()).c_str());
305
306 // Create output directory if does not exit.
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 // Determine new index and filename for each processor for
314 // parallel-in-time processing.
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 // Determine new command for each processor for parallel-in-time
321 // processing.
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;
332 ModuleKey module;
333 ModuleSharedPtr mod;
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 // Add input and output modules to beginning and end of this vector.
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 // For special case of part-only or part-only-overlapping options
352 // only require a single input file and so reset the nInputs to be
353 // of size inout.size(). Since the code will exit before reaching
354 // any output module this seems to work as expected
355 if (vm.count("part-only") || vm.count("part-only-overlapping"))
356 {
357 nInput = inout.size();
358 }
359
360 InputModuleSharedPtr inputModule;
361 string outfilename;
362
363 for (int i = 0; i < modcmds.size(); ++i)
364 {
365 // First split each command by the colon separator.
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 // Assume all modules are input unless last, or specified to be :out
374 module.first = (i < nInput ? eInputModule : eOutputModule);
375 if (tmp1.size() > 1 && tmp1.back() == "out")
376 {
377 module.first = eOutputModule;
378 tmp1.pop_back();
379 }
380
381 // If no colon detected, automatically detect mesh type from
382 // file extension. Otherwise override and use tmp1[1] as the
383 // module to load. This also allows us to pass options to
384 // input/output modules. So, for example, to override
385 // filename.xml to be read as vtk, you use:
386 //
387 // filename.xml:vtk:opt1=arg1:opt2=arg2
388 if (tmp1.size() == 1)
389 {
390 // First, let's try to guess the input format if we're dealing
391 // with input files.
392 string guess;
393
394 if (module.first == eInputModule)
395 {
396 guess = InputModule::GuessFormat(tmp1[0]);
397 }
398
399 // Found file type.
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 // Remove trailing separator from extension to allow
417 // folder inputs using file.fld/
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;
431 tmp1.push_back(string(module.first == eInputModule
432 ? "infile="
433 : "outfile=") +
434 tmp1[0]);
435 }
436 }
437 else
438 {
439 module.second = tmp1[1];
440 tmp1.push_back(string(module.first == eInputModule
441 ? "infile="
442 : "outfile=") +
443 tmp1[0]);
444 offset++;
445 }
446 }
447 else
448 {
449 module.first = eProcessModule;
450 module.second = tmp1[0];
451 }
452
453 // Create module.
454 mod = GetModuleFactory().CreateInstance(module, f);
455 modules.push_back(mod);
456
457 if (module.first == eInputModule)
458 {
459 inputModule = std::dynamic_pointer_cast<InputModule>(mod);
460 inputModule->AddFile(module.second, tmp1[0]);
461 }
462 else if (module.first == eOutputModule)
463 {
464 outfilename = tmp1[0];
465 if (nParts > 1)
466 {
467 // If nParts is specified then ensure output modules
468 // write out mutipile files.
469 mod->RegisterConfig("writemultiplefiles");
470 }
471 }
472
473 // Set options for this module.
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 // Ensure configuration options have been set.
496 mod->SetDefaults();
497 }
498
499 Array<OneD, int> modulesCount(SIZE_ModulePriority, 0);
500 for (int i = 0; i < modules.size(); ++i)
501 {
502 ++modulesCount[modules[i]->GetModulePriority()];
503 }
504
505 // Loading module prerequisites
506 for (int i = 0; i < modules.size(); ++i)
507 {
508 // Looping through listed prereqs and loading them
509 for (int j = 0; j < modules[i]->GetModulePrerequisites().size(); ++j)
510 {
512 modules[i]->GetModulePrerequisites()[j], f);
513 // Logic that prevents double loading
514 if (modulesCount[mod->GetModulePriority()] == 0)
515 {
516 ++modulesCount[mod->GetModulePriority()];
517 modules.push_back(mod);
518 mod->SetDefaults();
519 }
520 }
521 }
522
523 // Include equispacedoutput module if needed
524 if (modulesCount[eModifyPts] != 0 && modulesCount[eCreatePts] == 0 &&
525 modulesCount[eConvertExpToPts] == 0)
526 {
527 module.first = eProcessModule;
528 module.second = string("equispacedoutput");
529 mod = GetModuleFactory().CreateInstance(module, f);
530 modules.push_back(mod);
531 mod->SetDefaults();
532 }
533
534 // Check if modules provided are compatible.
535 CheckModules(modules);
536 // Can't have ContField with range option (because of boundaries).
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 {
546 PrintExecutionSequence(modules);
547 }
548
549 // Loop on partitions if required.
550 LibUtilities::CommSharedPtr defComm = f->m_comm;
552 for (int p = MPIrank; p < nParts; p += MPInprocs)
553 {
554 // Write out which partition is being processed and defined a
555 // new serial communicator.
556 if (nParts > 1)
557 {
558 cout << endl << "Processing partition: " << p << endl;
559
560 int rank = p;
561 f->ClearField();
562 partComm = std::shared_ptr<FieldConvertComm>(
563 new FieldConvertComm(argc, argv, nParts, rank));
564 }
565
566 // Run field process.
567 for (int n = 0; n < SIZE_ModulePriority; ++n)
568 {
569 ModulePriority priority = static_cast<ModulePriority>(n);
570
571 if (nParts > 1)
572 {
573 if (((priority == eCreateGraph) || (priority == eOutput)))
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 {
587 RunModule(modules[i], vm, verbose);
588 }
589 }
590 }
591 }
592
593 // Write out Info file if required.
594 if (nParts > 1)
595 {
596 int i;
597 // Check to see if we have created a fld file.
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 {
615 module.first = eOutputModule;
616 module.second = string("info");
617 mod = GetModuleFactory().CreateInstance(module, f);
618
619 mod->RegisterConfig("nparts",
620 boost::lexical_cast<string>(nParts));
621 mod->SetDefaults();
622
623 if (f->m_writeBndFld)
624 {
625 // Find ending of output file and insert _b1, _b2.
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);
638 RunModule(mod, vm, verbose);
639 }
640 }
641 else
642 {
643 mod->RegisterConfig("outfile", outfilename);
644 RunModule(mod, vm, verbose);
645 }
646 }
647 }
648 }
649
650 timer.Stop();
651
652 if (verbose)
653 {
654 NekDouble cpuTime = timer.TimePerTest(1);
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}
669
670// This function checks validity conditions for the list of modules provided
671void CheckModules(vector<ModuleSharedPtr> &modules)
672{
673 // Count number of modules by priority.
674 Array<OneD, int> modulesCount(SIZE_ModulePriority, 0);
675 for (int i = 0; i < modules.size(); ++i)
676 {
677 ++modulesCount[modules[i]->GetModulePriority()];
678 }
679
680 // Modules of type eModifyFieldData require a eCreateFieldData module.
681 if (modulesCount[eModifyFieldData] != 0 &&
682 modulesCount[eCreateFieldData] == 0)
683 {
684 stringstream ss;
685 ss << "Module(s): ";
686 for (int i = 0; i < modules.size(); ++i)
687 {
688 if (modules[i]->GetModulePriority() == eModifyFieldData)
689 {
690 ss << modules[i]->GetModuleName() << " ";
691 }
692 }
693 ss << "require fld input.";
694 ASSERTL0(false, ss.str());
695 }
696
697 // Modules of type eFillExp require eCreateGraph without eCreateFieldData.
698 if (modulesCount[eFillExp] != 0)
699 {
700 if (modulesCount[eCreateGraph] == 0 ||
701 modulesCount[eCreateFieldData] != 0)
702 {
703 stringstream ss;
704 ss << "Module(s): ";
705 for (int i = 0; i < modules.size(); ++i)
706 {
707 if (modules[i]->GetModulePriority() == eFillExp)
708 {
709 ss << modules[i]->GetModuleName() << " ";
710 }
711 }
712 ss << "require xml input without fld input.";
713 ASSERTL0(false, ss.str());
714 }
715 }
716
717 // Modules of type eModifyExp and eBndExtraction require a eCreateGraph
718 // module.
719 if ((modulesCount[eModifyExp] != 0 || modulesCount[eBndExtraction] != 0) &&
720 modulesCount[eCreateGraph] == 0)
721 {
722 stringstream ss;
723 ss << "Module(s): ";
724 for (int i = 0; i < modules.size(); ++i)
725 {
726 if (modules[i]->GetModulePriority() == eModifyExp ||
727 modules[i]->GetModulePriority() == eBndExtraction)
728 {
729 ss << modules[i]->GetModuleName() << " ";
730 }
731 }
732 ss << "require xml input.";
733 ASSERTL0(false, ss.str());
734 }
735
736 // Modules of type eCreatePts should not be used with xml or fld inputs.
737 if (modulesCount[eCreatePts] != 0)
738 {
739 if (modulesCount[eCreateGraph] != 0 ||
740 modulesCount[eCreateFieldData] != 0)
741 {
742 stringstream ss;
743 ss << "Module(s): ";
744 for (int i = 0; i < modules.size(); ++i)
745 {
746 if (modules[i]->GetModulePriority() == eCreatePts)
747 {
748 ss << modules[i]->GetModuleName() << " ";
749 }
750 }
751 ss << "should not use xml or fld inputs.";
752 ASSERTL0(false, ss.str());
753 }
754 }
755
756 // Modules of type eConvertExpToPts require eCreateGraph, but are not
757 // compatible with eBndExtraction.
758 if (modulesCount[eConvertExpToPts] != 0)
759 {
760 if (modulesCount[eCreateGraph] == 0)
761 {
762 stringstream ss;
763 ss << "Module(s): ";
764 for (int i = 0; i < modules.size(); ++i)
765 {
766 if (modules[i]->GetModulePriority() == eConvertExpToPts)
767 {
768 ss << modules[i]->GetModuleName() << " ";
769 }
770 }
771 ss << "require xml input.";
772 ASSERTL0(false, ss.str());
773 }
774 if (modulesCount[eBndExtraction] != 0)
775 {
776 stringstream ss;
777 ss << "Module(s): ";
778 for (int i = 0; i < modules.size(); ++i)
779 {
780 if (modules[i]->GetModulePriority() == eBndExtraction)
781 {
782 ss << modules[i]->GetModuleName() << " ";
783 }
784 }
785 ss << "is not compatible with module(s): ";
786 for (int i = 0; i < modules.size(); ++i)
787 {
788 if (modules[i]->GetModulePriority() == eConvertExpToPts)
789 {
790 ss << modules[i]->GetModuleName() << " ";
791 }
792 }
793 ss << ".";
794 ASSERTL0(false, ss.str());
795 }
796 }
797}
798
799// This function print the execution sequence for the list of modules provided
800void PrintExecutionSequence(vector<ModuleSharedPtr> &modules)
801{
802 bool first = true;
803 cout << "Execution sequence:" << endl;
804 for (int n = 0; n < SIZE_ModulePriority; ++n)
805 {
806 ModulePriority priority = static_cast<ModulePriority>(n);
807 for (int i = 0; i < modules.size(); ++i)
808 {
809 if (modules[i]->GetModulePriority() == priority)
810 {
811 if (first)
812 {
813 cout << "\t" << modules[i]->GetModuleName();
814 first = false;
815 }
816 else
817 {
818 cout << " -> " << modules[i]->GetModuleName();
819 }
820 }
821 }
822 }
823 cout << endl;
824}
825
826// This function run the module provided
827void RunModule(ModuleSharedPtr module, po::variables_map &vm, bool verbose)
828{
829 LibUtilities::Timer moduleTimer;
830 if (verbose)
831 {
832 moduleTimer.Start();
833
834 cout << module->GetModuleName() << ": "
835 << module->GetModuleDescription() << endl;
836 }
837 module->Process(vm);
838 cout.flush();
839 if (verbose)
840 {
841 moduleTimer.Stop();
842 NekDouble cpuTime = moduleTimer.TimePerTest(1);
843
844 stringstream ss;
845 ss << cpuTime << "s";
846 cout << module->GetModuleName() << " CPU Time: " << setw(8) << left
847 << ss.str() << endl;
848 }
849}
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:208
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.
Definition: Timer.cpp:65
def description(self, force=False, cellml=False)
Definition: pycml.py:2670
std::shared_ptr< Field > FieldSharedPtr
Definition: Field.hpp:1026
std::pair< ModuleType, std::string > ModuleKey
Definition: Module.h:180
std::shared_ptr< InputModule > InputModuleSharedPtr
Definition: Module.h:294
std::shared_ptr< Module > ModuleSharedPtr
Definition: Module.h:329
ModuleFactory & GetModuleFactory()
Definition: Module.cpp:47
CommFactory & GetCommFactory()
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:55
std::vector< double > d(NPUPPER *NPUPPER)
double NekDouble
STL namespace.