1 // Project MULTIPR, IOLS WP1.2.1 - EDF/CS
2 // Partitioning/decimation module for the SALOME v3.2 platform
7 * \brief Standalone command line application of the MULTIPR component.
8 * The application aims to reduce large data set to allow interactive visualization.
9 * Its two main function are the following:
10 * 1. Splits any TETRA10 mesh contained in a MED file.
11 * a. Builds a distributed MED file by extracting all the groups from a sequential MED file.
12 * b. Splits a part of distributed MED file.
13 * 2. Decimates fields to produce multi-resolution data set.
15 * Return 0 if application succeed, 1 otherwise (failure).
17 * See http://www.salome-platform.org to learn more about Salome or MED.
19 * \author Olivier LE ROUX - CS, Virtual Reality Dpt
24 #include "MULTIPR_API.hxx"
25 #include "MULTIPR_Obj.hxx"
26 #include "MULTIPR_Mesh.hxx"
27 #include "MULTIPR_Exceptions.hxx"
28 #include "MULTIPR_Utils.hxx"
37 // This command line application can use 2 differents API to do the same work.
38 // If MULTIPR_USE_OBJ_API is defined then this command line application used the MULTIPR_Obj API;
39 // otherwise, it uses the MULTIPR_API
40 //#define MULTIPR_USE_OBJ_API
43 const int MULTIPR_APP_OK = 0;
44 const int MULTIPR_APP_FAILED = 1;
48 * Enumerates all the usages of this application.
52 MULTIPR_USAGE_UNKNOWN,
53 MULTIPR_USAGE_DISPLAY_HELP,
54 MULTIPR_USAGE_AUTOTEST,
55 MULTIPR_USAGE_PARTITION1,
56 MULTIPR_USAGE_PARTITION2,
57 MULTIPR_USAGE_DECIMATION,
63 * Enumerates all the possible errors.
68 MULTIPR_APP_UNKNOWN_USAGE,
69 MULTIPR_APP_WRONG_NUMBER_OF_ARGUMENTS,
70 MULTIPR_APP_ILLEGAL_ARGUMENT,
71 MULTIPR_APP_FILE_NOT_FOUND,
73 MULTIPR_APP_UNDEFINED_ERROR
77 // global variables used to configure the application
79 int g_errorCode = MULTIPR_APP_NO_ERROR;
80 char* g_medFilename = NULL;
81 char* g_meshName = NULL;
82 char* g_partName = NULL;
84 char* g_filterName = NULL;
85 char* g_fieldName = NULL;
86 int g_fieldTimeStepIt = 0;
87 float g_decimThresholdMed = 0.0f;
88 float g_decimThresholdLow = 0.0f;
89 float g_decimRadius = 0.0f;
94 * \fn const char* getUsage(int usage)
95 * \brief returns a string describing the usage of this application.
97 const char* getUsage(int usage)
101 case MULTIPR_USAGE_DISPLAY_HELP:
102 return "--help: display help";
104 case MULTIPR_USAGE_AUTOTEST:
105 return "--auto: unit tests";
107 case MULTIPR_USAGE_PARTITION1:
108 return "--part1: extract all groups of a sequential MED file";
110 case MULTIPR_USAGE_PARTITION2:
111 return "--part2: split a part of a distributed MED file";
113 case MULTIPR_USAGE_DECIMATION:
114 return "--decim: generated level of details of a part of a distributed MED file";
116 case MULTIPR_USAGE_INFO:
117 return "--info: prints all infos about a mesh in a sequential MED file";
126 * \fn void printDescription()
127 * \brief prints a short description of this application.
129 void printDescription()
131 cout << "Keywords:" << endl;
132 cout << " Post-processing numerical simulation, Salome platform, " << endl;
133 cout << " Large data set visualization, 3D meshes and fields" << endl;
134 cout << "Description:" << endl;
135 cout << " multipr is a partitionning/decimation tool of MED files." << endl;
136 cout << " See http://www.salome-platform.org for information about MED or Salome." << endl;
137 cout << " Note: current version only accept TETRA10 meshes." << endl;
142 * \fn void printUsage()
143 * \brief prints "how to use" manual of this tools.2NbPart
147 cout << "Usages:" << endl;
148 cout << " --auto Autotest: performs some unit tests on the MULTIPR API" << endl;
149 cout << " * Usage: --auto path (path where to find test file \"agregat100grains_12pas.med\")" << endl;
150 cout << " --part1 Extracts all groups from a sequential MED file (V2.2 or higher)" << endl;
151 cout << " * Usage: --part1 file.med meshName" << endl;
152 cout << " --part2 Split a group of a distributed MED file (V2.3) produced with --part1" << endl;
153 cout << " * Usage: --part2 file.med partName nbParts" << endl;
154 cout << " --decim Generates 3 level of details (full, medium and low) of a part" << endl;
155 cout << " of a distributed MED file (V2.3)" << endl;
156 cout << " * Usage: --decim file.med partName fieldName fieldIt filterName [...]" << endl;
157 cout << " * Only one filter is currently available: Filtre_GradientMoyen" << endl;
158 cout << " * Usage: --decim file.med partName fieldName fieldIt Filtre_GradientMoyen m l radius" << endl;
159 cout << " where m=threshold for medium res. and l=threshold for low res.; assume m < l" << endl;
160 cout << " --info Dumps all infos related to a mesh in a sequential MED file" << endl;
161 cout << " * Usage: --info file.med [meshName]" << endl;
162 cout << " --help Displays this help page" << endl;
168 * \fn void printGlobals()
169 * \brief print current state of all global variables.
174 cout << "********************************************************************************" << endl;
175 cout << "CONFIGURATION" << endl;
176 cout << "--------------------------------------------------------------------------------" << endl;
177 cout << "Mode : " << getUsage(g_usage) << endl;
178 cout << "Med filename : " << ((g_medFilename != NULL) ? g_medFilename : "UNDEFINED") << endl;
179 cout << "Mesh name : " << ((g_meshName != NULL) ? g_meshName : "UNDEFINED") << endl;
180 cout << "Part name : " << ((g_partName != NULL) ? g_partName : "UNDEFINED") << endl;
181 cout << "Nb parts : " << g_nbParts << endl;
182 cout << "Decimation:" << endl;
183 cout << " Field name : " << ((g_fieldName != NULL) ? g_fieldName : "UNDEFINED") << endl;
184 cout << " Time step iteration : " << g_fieldTimeStepIt << endl;
185 cout << " Filter name : " << ((g_filterName != NULL) ? g_filterName : "UNDEFINED") << endl;
186 cout << " Threshold for med. res. : " << g_decimThresholdMed << endl;
187 cout << " Threshold for low res. : " << g_decimThresholdLow << endl;
188 cout << " Radius : " << g_decimRadius << endl;
189 cout << " Boxing : " << g_boxing << endl;
190 cout << "********************************************************************************" << endl;
196 * \fn const char* getErrorMsg()
197 * \brief returns the error message corresponding to current error code.
198 * \return the current error message.
200 const char* getErrorMsg()
204 case MULTIPR_APP_NO_ERROR:
207 case MULTIPR_APP_UNKNOWN_USAGE:
208 return "unknown usage";
210 case MULTIPR_APP_WRONG_NUMBER_OF_ARGUMENTS:
211 return "wrong number of arguments";
213 case MULTIPR_APP_ILLEGAL_ARGUMENT:
214 return "illegal argument";
216 case MULTIPR_APP_FILE_NOT_FOUND:
217 return "file not found";
219 case MULTIPR_APP_IO_ERROR:
223 return "error (undefined)";
229 * \fn void parseCommandLine(int argc, char** argv)
230 * \brief parses the command line and configure this application.
231 * \param argc number of arguments.
232 * \param argv array of arguments.
234 void parseCommandLine(int argc, char** argv)
238 g_usage = MULTIPR_USAGE_UNKNOWN;
242 if (strcmp(argv[1],"--help") == 0)
244 g_usage = MULTIPR_USAGE_DISPLAY_HELP;
246 else if (strcmp(argv[1],"--auto") == 0)
250 g_usage = MULTIPR_USAGE_UNKNOWN;
251 g_errorCode = MULTIPR_APP_WRONG_NUMBER_OF_ARGUMENTS;
255 g_usage = MULTIPR_USAGE_AUTOTEST;
256 g_medFilename = argv[2];
259 else if (strcmp(argv[1],"--part1") == 0)
263 g_usage = MULTIPR_USAGE_UNKNOWN;
264 g_errorCode = MULTIPR_APP_WRONG_NUMBER_OF_ARGUMENTS;
268 g_usage = MULTIPR_USAGE_PARTITION1;
269 g_medFilename = argv[2];
270 g_meshName = argv[3];
273 else if (strcmp(argv[1],"--part2") == 0)
277 g_usage = MULTIPR_USAGE_UNKNOWN;
278 g_errorCode = MULTIPR_APP_WRONG_NUMBER_OF_ARGUMENTS;
282 g_usage = MULTIPR_USAGE_PARTITION2;
283 g_medFilename = argv[2];
284 g_partName = argv[3];
285 g_nbParts = atoi(argv[4]);
288 else if (strcmp(argv[1],"--decim") == 0)
290 if ((argc != 10) && (argc != 11))
292 g_usage = MULTIPR_USAGE_UNKNOWN;
293 g_errorCode = MULTIPR_APP_WRONG_NUMBER_OF_ARGUMENTS;
297 g_usage = MULTIPR_USAGE_DECIMATION;
298 g_medFilename = argv[2];
299 g_partName = argv[3];
300 g_fieldName = argv[4];
301 g_fieldTimeStepIt = atoi(argv[5]);
302 g_filterName = argv[6];
303 g_decimThresholdMed = atof(argv[7]);
304 g_decimThresholdLow = atof(argv[8]);
305 g_decimRadius = atof(argv[9]);
309 g_boxing = atoi(argv[10]);
313 else if (strcmp(argv[1],"--info") == 0)
315 if ((argc != 3) && (argc != 4))
317 g_usage = MULTIPR_USAGE_UNKNOWN;
318 g_errorCode = MULTIPR_APP_WRONG_NUMBER_OF_ARGUMENTS;
322 g_usage = MULTIPR_USAGE_INFO;
323 g_medFilename = argv[2];
327 g_meshName = argv[3];
333 g_usage = MULTIPR_USAGE_UNKNOWN;
334 g_errorCode = MULTIPR_APP_UNKNOWN_USAGE;
340 * \fn int runAutotest()
341 * \brief performs some unit tests on the MULTIPR API.
342 * \return MULTIPR_APP_OK if successful, MULTIPR_APP_FAILED if failure.
346 cout << "Start autotest..." << endl;
348 int ret = MULTIPR_APP_OK;
351 string strMEDfilename = g_medFilename;
352 strMEDfilename += "/agregat100grains_12pas.med";
354 cout << "Test file: " << strMEDfilename << endl << endl;
356 //---------------------------------------------------------------------
357 // Test partionneDomaine() = extract groups from a sequential MED file
358 //---------------------------------------------------------------------
359 multipr::partitionneDomaine(strMEDfilename.c_str(), "MAIL");
361 //---------------------------------------------------------------------
362 // Test partitionneGrain() = split a group from a distributed MED file
363 // using MEDSPLITTER (METIS)
364 //---------------------------------------------------------------------
365 string strDistributedMEDfilename = g_medFilename;
366 strDistributedMEDfilename += "/agregat100grains_12pas_grains_maitre.med";
368 multipr::partitionneGrain(
369 strDistributedMEDfilename.c_str(),
372 multipr::MULTIPR_SCOTCH);
374 multipr::partitionneGrain(
375 strDistributedMEDfilename.c_str(),
378 multipr::MULTIPR_METIS);
380 //---------------------------------------------------------------------
381 // Test decimePartition() = generate 2 lower resolution of a mesh
382 // using decimation based on gradient
383 //---------------------------------------------------------------------
384 multipr::decimePartition(
385 strDistributedMEDfilename.c_str(),
387 "SIG_____SIEF_ELGA_______________",
389 "Filtre_GradientMoyen",
395 multipr::decimePartition(
396 strDistributedMEDfilename.c_str(),
398 "SIG_____SIEF_ELGA_______________",
400 "Filtre_GradientMoyen",
406 multipr::decimePartition(
407 strDistributedMEDfilename.c_str(),
409 "SIG_____SIEF_ELGA_______________",
411 "Filtre_GradientMoyen",
417 //---------------------------------------------------------------------
419 //---------------------------------------------------------------------
421 cout << "Test passed: everything seems to be OK" << endl;
422 cout << "OK" << endl << endl;
425 catch (multipr::RuntimeException& e)
429 cout << "Test failed" << endl;
430 cout << "Failure" << endl << endl;
431 ret = MULTIPR_APP_FAILED;
439 * \fn void runPartition1()
440 * \brief builds a distributed MED file (v2.3) by extracting groups from a sequential MED file.
441 * \return MULTIPR_APP_OK if successful, MULTIPR_APP_FAILED if failure.
445 int ret = MULTIPR_APP_OK;
448 multipr::partitionneDomaine(g_medFilename, g_meshName);
450 catch (multipr::RuntimeException& e)
453 ret = MULTIPR_APP_FAILED;
461 * \fn void runPartition2()
462 * \brief builds a distributed MED file (v2.3) by splitting a part of a distributed MED file generated by runPartition1().
463 * \return MULTIPR_APP_OK if successful, MULTIPR_APP_FAILED if failure.
467 int ret = MULTIPR_APP_OK;
470 multipr::partitionneGrain(
474 multipr::MULTIPR_METIS);
476 catch (multipr::RuntimeException& e)
479 ret = MULTIPR_APP_FAILED;
487 * \fn int runDecimation()
488 * \brief creates 3 resolutions of a part of a distributed MED file.
489 * \return MULTIPR_APP_OK if successful, MULTIPR_APP_FAILED if failure.
493 int ret = MULTIPR_APP_OK;
496 multipr::decimePartition(
507 catch (multipr::RuntimeException& e)
510 ret = MULTIPR_APP_FAILED;
518 * \fn int runDumpMED()
519 * \brief dumps info about a sequential MED file.
520 * \return MULTIPR_APP_OK if successful, MULTIPR_APP_FAILED if failure.
524 #ifdef MULTIPR_USE_OBJ_API
525 int ret = MULTIPR_APP_OK;
528 // if mesh is unknown, then list all the meshes in the given MED file
529 if (g_meshName == NULL)
532 obj.create(g_medFilename);
535 // display list of meshes contained in the MED file
536 vector<string> res = obj.getMeshes();
537 cout << "List of meshes in this MED file:" << endl;
538 for (unsigned i = 0 ; i < res.size() ; i++)
540 cout << "Mesh " << (i + 1) << ": " << res[i] << endl;
547 // display list of fields contained in the MED file
548 vector<string> names = obj.getFields();
549 cout << "List of fields in this MED file:" << endl;
550 for (unsigned i = 0 ; i < names.size() ; i++)
552 cout << "Field " << (i + 1) << ": " << names[i] << " #it=" << obj.getTimeStamps(names[i].c_str()) << endl;
558 // display all infos about one mesh in a MED file
560 mesh.readSequentialMED(g_medFilename, g_meshName);
561 mesh.setPrintAll(true);
562 cout << mesh << endl;
564 cout << "OK" << endl;
566 catch (multipr::RuntimeException& e)
569 ret = MULTIPR_APP_FAILED;
574 int ret = MULTIPR_APP_OK;
577 // if mesh is unknown, then list all the meshes in the given MED file
578 if (g_meshName == NULL)
581 // display list of meshes contained in the MED file
582 vector<string> res = multipr::getListMeshes(g_medFilename);
583 cout << "List of meshes in this MED file:" << endl;
584 for (unsigned i = 0 ; i < res.size() ; i++)
586 cout << "Mesh " << (i + 1) << ": " << res[i] << endl;
593 // display list of fields contained in the MED file
594 vector<pair<string,int> > res = multipr::getListScalarFields(g_medFilename);
595 cout << "List of fields in this MED file:" << endl;
596 for (unsigned i = 0 ; i < res.size() ; i++)
598 cout << "Field " << (i + 1) << ": " << res[i].first << " #it=" << res[i].second << endl;
604 // display all infos about one mesh in a MED file
606 mesh.readSequentialMED(g_medFilename, g_meshName);
607 mesh.setPrintAll(true);
608 cout << mesh << endl;
610 cout << "OK" << endl;
612 catch (multipr::RuntimeException& e)
615 ret = MULTIPR_APP_FAILED;
625 * \brief applies partitioning/decimation according to global parameters.
626 * \return MULTIPR_APP_OK if successful, MULTIPR_APP_FAILED if failure.
632 int ret = MULTIPR_APP_OK;
635 case MULTIPR_USAGE_AUTOTEST: ret = runAutotest(); break;
636 case MULTIPR_USAGE_PARTITION1: ret = runPartition1(); break;
637 case MULTIPR_USAGE_PARTITION2: ret = runPartition2(); break;
638 case MULTIPR_USAGE_DECIMATION: ret = runDecimation(); break;
639 case MULTIPR_USAGE_INFO: ret = runDumpMED(); break;
641 cout << "ERROR: unknown usage" << endl;
642 ret = MULTIPR_APP_FAILED;
651 * \fn int main(int argc, char** argv)
652 * \brief entry point of the application.
653 * \param argc number of arguments.
654 * \param argv list of arguments.
655 * \return 0 if OK, 1 if failed.
657 int main(int argc, char** argv)
659 cout << "multipr v" << multipr::getVersion() << " - by EDF/CS - 01/2007" << endl;
660 cout << "==================================" << endl;
662 #ifdef MULTIPR_USE_OBJ_API
663 cout << "Version MULTIPR_Obj" << endl;
665 cout << "Version MULTIPR_API" << endl;
668 parseCommandLine(argc, argv);
670 int ret = MULTIPR_APP_OK; // assume no error at the beginning
672 if (g_usage == MULTIPR_USAGE_UNKNOWN)
676 // if usage is unknown and there are some arguments, print an error message
677 cout << "ERROR: " << getErrorMsg() << endl;
679 ret = MULTIPR_APP_FAILED;
683 // if no argument, print a description of this application
689 else if (g_usage == MULTIPR_USAGE_DISPLAY_HELP)
696 // the application seems to be configured properly: it can be executed