Nektar++
Functions
NekMesh.cpp File Reference
#include <LibUtilities/BasicConst/GitRevision.h>
#include <LibUtilities/BasicUtils/Timer.h>
#include <boost/algorithm/string.hpp>
#include <boost/asio/ip/host_name.hpp>
#include <boost/format.hpp>
#include <boost/program_options.hpp>
#include <string>
#include <NekMesh/Module/Module.h>

Go to the source code of this file.

Functions

int main (int argc, char *argv[])
 

Function Documentation

◆ main()

int main ( int  argc,
char *  argv[] 
)

Definition at line 51 of file NekMesh.cpp.

52{
53 po::options_description desc("Available options");
54 po::options_description dep("Deprecated options");
55
56 // clang-format off
57 desc.add_options()
58 ("help,h", "Produce this help message.")
59 ("force-output,f", "Force the output to be written without any checks")
60 ("modules-list,l", "Print the list of available modules.")
61 ("modules-opt,p", po::value<string>(),
62 "Print options for a module.")
63 ("module,m", po::value<vector<string> >(),
64 "Specify modules which are to be used.")
65 ("verbose,v", "Enable verbose output.");
66 // clang-format on
67
68 po::options_description hidden("Hidden options");
69
70 // clang-format off
71 hidden.add_options()
72 ("input-file", po::value<vector<string> >(), "Input filename");
73 // clang-format on
74
75 // Deprecated options: introduced in 5.4.0 to homogenise command-line
76 // options to use '-' instead of camelCase or no spaces.
77 std::map<std::string, std::string> deprecated = {
78 {"forceoutput", "force-output"}};
79
80 for (auto &d : deprecated)
81 {
82 std::string description = "Deprecated: use --" + d.second;
83 dep.add_options()(d.first.c_str(), description.c_str());
84 }
85
86 po::options_description cmdline_options;
87 cmdline_options.add(hidden).add(desc).add(dep);
88
89 po::positional_options_description p;
90 p.add("input-file", -1);
91
92 po::variables_map vm;
93
94 try
95 {
96 po::store(po::command_line_parser(argc, argv)
97 .options(cmdline_options)
98 .positional(p)
99 .run(),
100 vm);
101 po::notify(vm);
102 }
103 catch (const std::exception &e)
104 {
105 cerr << e.what() << endl;
106 cerr << desc;
107 return 1;
108 }
109
110 // If NEKTAR_DISABLE_BACKUPS environment variable is set, enable the
111 // force-output option.
112 if (std::getenv("NEKTAR_DISABLE_BACKUPS") != nullptr)
113 {
114 vm.insert(std::make_pair("force-output", po::variable_value()));
115 }
116
117 // Create a logger.
118 auto logOutput = std::make_shared<StreamOutput>(std::cout);
119 Logger log(logOutput, vm.count("verbose") ? VERBOSE : INFO);
120
121 // Deal with deprecated options.
122 for (auto &d : deprecated)
123 {
124 if (vm.count(d.first))
125 {
126 log(WARNING) << "--" << d.first << " deprecated: use --" << d.second
127 << std::endl;
128 vm.emplace(d.second, po::variable_value(vm[d.first]));
129 }
130 }
131
132 // Print available modules.
133 if (vm.count("modules-list"))
134 {
136 return 1;
137 }
138
139 if (vm.count("modules-opt"))
140 {
141 vector<string> tmp1;
142 boost::split(tmp1, vm["modules-opt"].as<string>(),
143 boost::is_any_of(":"));
144
145 if (tmp1.size() != 2)
146 {
147 cerr << "ERROR: To specify a module, use one of in, out or proc "
148 << "together with the filename; for example in:vtk." << endl;
149 return 1;
150 }
151
152 if (tmp1[0] != "in" && tmp1[0] != "out" && tmp1[0] != "proc")
153 {
154 cerr << "ERROR: Invalid module type (in, out, or proc): " << tmp1[0]
155 << endl;
156 return 1;
157 }
158
160
161 if (tmp1[0] == "in")
162 {
163 t = eInputModule;
164 }
165 else if (tmp1[0] == "out")
166 {
167 t = eOutputModule;
168 }
169 else if (tmp1[0] == "proc")
170 {
171 t = eProcessModule;
172 }
173
174 MeshSharedPtr m = std::shared_ptr<Mesh>(new Mesh());
175 ModuleSharedPtr mod =
176 GetModuleFactory().CreateInstance(ModuleKey(t, tmp1[1]), m);
177 cerr << "Options for module " << tmp1[1] << ":" << endl;
178 mod->SetLogger(log);
179 mod->PrintConfig();
180 return 1;
181 }
182
183 if (vm.count("help") || vm.count("input-file") != 1)
184 {
185 cerr << "Usage: NekMesh [options] inputfile.ext1 outputfile.ext2"
186 << endl;
187 cout << desc;
188 return 1;
189 }
190
191 vector<string> inout = vm["input-file"].as<vector<string>>();
192
193 if (inout.size() != 2)
194 {
195 cerr << "ERROR: You must specify an input and output file." << endl;
196 return 1;
197 }
198
199 /*
200 * Process list of modules. Each element of the vector of module strings can
201 * be in the following form:
202 *
203 * modname:arg1=a:arg2=b:arg3=c:arg4:arg5=asd
204 *
205 * where the only required argument is 'modname', specifing the name of the
206 * module to load.
207 */
208
209 MeshSharedPtr mesh = std::shared_ptr<Mesh>(new Mesh());
210
211 // Add provenance information to mesh.
212 stringstream ss;
213 for (int i = 1; i < argc; i++)
214 {
215 ss << argv[i] << " ";
216 }
217 mesh->m_metadata["NekMeshCommandLine"] = ss.str();
218
219 vector<ModuleSharedPtr> modules;
220 vector<string> modcmds;
221
222 if (vm.count("module"))
223 {
224 modcmds = vm["module"].as<vector<string>>();
225 }
226
227 bool forceOutput = vm.count("force-output");
228
229 // Add input and output modules to beginning and end of this vector.
230 modcmds.insert(modcmds.begin(), inout[0]);
231 modcmds.push_back(inout[1]);
232
233 // Keep track of maximum string length for nicer verbose output.
234 size_t maxModName = 0;
235
236 for (int i = 0; i < modcmds.size(); ++i)
237 {
238 // First split each command by the colon separator.
239 vector<string> tmp1;
240 ModuleKey module;
241 int offset = 1;
242
243 boost::split(tmp1, modcmds[i], boost::is_any_of(":"));
244
245 if (i == 0 || i == modcmds.size() - 1)
246 {
247 module.first = (i == 0 ? eInputModule : eOutputModule);
248
249 // If no colon detected, automatically detect mesh type from
250 // file extension. Otherwise override and use tmp1[1] as the
251 // module to load. This also allows us to pass options to
252 // input/output modules. So, for example, to override
253 // filename.xml to be read as vtk, you use:
254 //
255 // filename.xml:vtk:opt1=arg1:opt2=arg2
256 if (tmp1.size() == 1)
257 {
258 int dot = tmp1[0].find_last_of('.') + 1;
259 string ext = tmp1[0].substr(dot, tmp1[0].length() - dot);
260
261 if (ext == "gz")
262 {
263 string tmp = tmp1[0].substr(0, tmp1[0].length() - 3);
264 dot = tmp.find_last_of('.') + 1;
265 ext = tmp.substr(dot, tmp.length() - dot);
266 }
267
268 module.second = ext;
269 tmp1.push_back(string(i == 0 ? "infile=" : "outfile=") +
270 tmp1[0]);
271 }
272 else
273 {
274 module.second = tmp1[1];
275 tmp1.push_back(string(i == 0 ? "infile=" : "outfile=") +
276 tmp1[0]);
277 offset++;
278 }
279 }
280 else
281 {
282 module.first = eProcessModule;
283 module.second = tmp1[0];
284 }
285
286 // Create module.
287 ModuleSharedPtr mod = GetModuleFactory().CreateInstance(module, mesh);
288 mod->SetLogger(log);
289 modules.push_back(mod);
290
291 // Set options for this module.
292 for (int j = offset; j < tmp1.size(); ++j)
293 {
294 vector<string> tmp2;
295 boost::split(tmp2, tmp1[j], boost::is_any_of("="));
296
297 if (tmp2.size() == 1)
298 {
299 mod->RegisterConfig(tmp2[0]);
300 }
301 else if (tmp2.size() == 2)
302 {
303 mod->RegisterConfig(tmp2[0], tmp2[1]);
304 }
305 else
306 {
307 cerr << "ERROR: Invalid module configuration: format is "
308 << "either :arg or :arg=val" << endl;
309 return 1;
310 }
311 }
312
313 if (i == modcmds.size() - 1 && forceOutput)
314 {
315 mod->RegisterConfig("forceoutput", "true");
316 }
317
318 // Ensure configuration options have been set.
319 mod->SetDefaults();
320
321 // Track maximum module name length.
322 std::string modName = mod->GetModuleName();
323 maxModName = std::max(maxModName, modName.length());
324 }
325
326 log.SetPrefixLen(maxModName);
327
328 // Run mesh process.
329 for (int i = 0; i < modules.size(); ++i)
330 {
332 t.Start();
333 try
334 {
335 modules[i]->GetLogger().SetPrefixLen(maxModName);
336 modules[i]->Process();
337 }
338 catch (NekMeshError &e)
339 {
340 return 1;
341 }
342 t.Stop();
343
344 log.SetPrefix(modules[i]->GetModuleName());
345 log(VERBOSE) << " - Elapsed time: " << t.TimePerTest(1) << "s."
346 << std::endl;
347 }
348
349 return 0;
350}
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:143
void PrintAvailableClasses(std::ostream &pOut=std::cout)
Prints the available classes to stdout.
Definition: NekFactory.hpp:231
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::pair< ModuleType, std::string > ModuleKey
Definition: Module.h:180
std::shared_ptr< Module > ModuleSharedPtr
Definition: Module.h:329
ModuleFactory & GetModuleFactory()
Definition: Module.cpp:47
std::vector< double > d(NPUPPER *NPUPPER)
scalarT< T > log(scalarT< T > in)
Definition: scalar.hpp:303

References Nektar::LibUtilities::NekFactory< tKey, tBase, tParam >::CreateInstance(), Nektar::UnitTests::d(), CellMLToNektar.pycml::description(), Nektar::FieldUtils::eInputModule, Nektar::FieldUtils::eOutputModule, Nektar::FieldUtils::eProcessModule, Nektar::FieldUtils::GetModuleFactory(), tinysimd::log(), CG_Iterations::Mesh, CellMLToNektar.cellml_metadata::p, Nektar::LibUtilities::NekFactory< tKey, tBase, tParam >::PrintAvailableClasses(), CellMLToNektar.translators::run(), Nektar::LibUtilities::Timer::Start(), Nektar::LibUtilities::Timer::Stop(), and Nektar::LibUtilities::Timer::TimePerTest().