]> SALOME platform Git repositories - modules/multipr.git/blob - src/MULTIPR/multipr.cxx
Salome HOME
*** empty log message ***
[modules/multipr.git] / src / MULTIPR / multipr.cxx
1 // Project MULTIPR, IOLS WP1.2.1 - EDF/CS
2 // Partitioning/decimation module for the SALOME v3.2 platform
3
4 /**
5  * \file    multipr.cxx
6  *
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.
14  *
15  *          Return 0 if application succeed, 1 otherwise (failure).
16  *
17  *          See http://www.salome-platform.org to learn more about Salome or MED.
18  *
19  * \author  Olivier LE ROUX - CS, Virtual Reality Dpt
20  * 
21  * \date    01/2007
22  */
23
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"
29
30 #include <iostream>
31 #include <vector>
32 #include <string>
33
34 using namespace std;
35
36
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
41
42
43 const int MULTIPR_APP_OK     = 0;
44 const int MULTIPR_APP_FAILED = 1;
45
46
47 /**
48  * Enumerates all the usages of this application.
49  */
50 enum Usage
51 {
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,
58         MULTIPR_USAGE_INFO
59 };
60
61
62 /**
63  * Enumerates all the possible errors.
64  */
65 enum Error
66 {
67         MULTIPR_APP_NO_ERROR,
68         MULTIPR_APP_UNKNOWN_USAGE,
69         MULTIPR_APP_WRONG_NUMBER_OF_ARGUMENTS,
70         MULTIPR_APP_ILLEGAL_ARGUMENT,
71         MULTIPR_APP_FILE_NOT_FOUND,
72         MULTIPR_APP_IO_ERROR,
73         MULTIPR_APP_UNDEFINED_ERROR
74 };
75
76
77 // global variables used to configure the application
78 int   g_usage               = 0; 
79 int   g_errorCode           = MULTIPR_APP_NO_ERROR;
80 char* g_medFilename         = NULL;
81 char* g_meshName            = NULL;
82 char* g_partName            = NULL;
83 int   g_nbParts             = 0;
84 int   g_splitter            = multipr::MULTIPR_METIS;
85 char* g_filterName          = NULL;
86 char* g_fieldName           = NULL;
87 int   g_fieldTimeStepIt     = 0;
88 float g_decimThresholdMed   = 0.0f;
89 float g_decimThresholdLow   = 0.0f;
90 float g_decimRadius         = 0.0f;
91 int   g_boxing              = 100;
92
93
94 /**
95  * \fn     const char* getUsage(int usage)
96  * \brief  returns a string describing the usage of this application.
97  */
98 const char* getUsage(int usage)
99 {
100         switch(usage)
101         {
102                 case MULTIPR_USAGE_DISPLAY_HELP:
103                         return "--help: display help";
104                         
105                 case MULTIPR_USAGE_AUTOTEST:
106                         return "--auto: unit tests";
107
108                 case MULTIPR_USAGE_PARTITION1:
109                         return "--part1: extract all groups of a sequential MED file";
110
111                 case MULTIPR_USAGE_PARTITION2:
112                         return "--part2: split a part of a distributed MED file";
113
114                 case MULTIPR_USAGE_DECIMATION:
115                         return "--decim: generated level of details of a part of a distributed MED file";
116                         
117                 case MULTIPR_USAGE_INFO:
118                         return "--info: prints all infos about a mesh in a sequential MED file";
119
120                 default:
121                         return "unknown";
122         }
123 }
124
125
126 /**
127  * \fn     void printDescription()
128  * \brief  prints a short description of this application.
129  */
130 void printDescription()
131 {
132         cout << "Keywords:" << endl;          
133         cout << "    Post-processing numerical simulation, Salome platform, " << endl;
134         cout << "    Large data set visualization, 3D meshes and fields" << endl;
135         cout << "Description:" << endl;
136         cout << "    multipr is a partitionning/decimation tool of MED files." << endl;
137         cout << "    See http://www.salome-platform.org for information about MED or Salome." << endl;
138         cout << "    Note: current version only accept TETRA10 meshes." << endl;
139 }
140
141
142 /**
143  * \fn     void printUsage()
144  * \brief  prints "how to use" manual of this tools.2NbPart
145  */
146 void printUsage()
147 {
148         cout << "Usages:" << endl;
149         cout << "    --auto   Autotest: performs some unit tests on the MULTIPR API" << endl;
150         cout << "                 * Usage: --auto path (path where to find test file \"agregat100grains_12pas.med\")" << endl;
151         cout << "    --part1  Extracts all groups from a sequential MED file (V2.2 or higher)" << endl;
152         cout << "                 * Usage: --part1 file.med meshName" << endl; 
153         cout << "    --part2  Split a group of a distributed MED file (V2.3) produced with --part1" << endl;
154         cout << "                 * Usage: --part2 file.med partName nbParts [splitter (0=METIS 1=SCOTCH)]" << endl;
155         cout << "    --decim  Generates 3 level of details (full, medium and low) of a part" << endl;
156         cout << "             of a distributed MED file (V2.3)" << endl;     
157         cout << "                 * Usage: --decim file.med partName fieldName fieldIt filterName [...]" << endl;
158         cout << "                 * Only one filter is currently available: Filtre_GradientMoyen" << endl;
159         cout << "                 * Usage: --decim file.med partName fieldName fieldIt Filtre_GradientMoyen m l radius" << endl;
160         cout << "                   where m=threshold for medium res. and l=threshold for low res.; assume m < l" << endl;
161         cout << "    --info   Dumps all infos related to a mesh in a sequential MED file" << endl;
162         cout << "                 * Usage: --info file.med [meshName]" << endl;
163         cout << "    --help   Displays this help page" << endl;
164         cout << endl;
165 }
166
167
168 /**
169  * \fn     void printGlobals()
170  * \brief  print current state of all global variables.
171  */
172 void printGlobals()
173 {
174         cout << endl;
175         cout << "********************************************************************************" << endl;
176         cout << "CONFIGURATION" << endl;
177         cout << "--------------------------------------------------------------------------------" << endl;
178         cout << "Mode                        : " << getUsage(g_usage) << endl;
179         cout << "Med filename                : " << ((g_medFilename != NULL) ? g_medFilename : "UNDEFINED") << endl;
180         cout << "Mesh name                   : " << ((g_meshName != NULL) ? g_meshName : "UNDEFINED") << endl;
181         cout << "Part name                   : " << ((g_partName != NULL) ? g_partName : "UNDEFINED") << endl;
182         cout << "Nb parts                    : "  << g_nbParts << endl;
183         cout << "Decimation:" << endl;
184         cout << "    Field name              : " << ((g_fieldName != NULL) ? g_fieldName : "UNDEFINED") << endl;
185         cout << "    Time step iteration     : " << g_fieldTimeStepIt << endl;
186         cout << "    Filter name             : " << ((g_filterName != NULL) ? g_filterName : "UNDEFINED") << endl;
187         cout << "    Threshold for med. res. : " << g_decimThresholdMed << endl;
188         cout << "    Threshold for low res.  : " << g_decimThresholdLow << endl;
189         cout << "    Radius                  : " << g_decimRadius << endl;
190         cout << "    Boxing                  : " << g_boxing << endl;
191         cout << "********************************************************************************" << endl;
192         cout << endl;
193 }
194
195
196 /**
197  * \fn     const char* getErrorMsg()
198  * \brief  returns the error message corresponding to current error code.
199  * \return the current error message.
200  */
201 const char* getErrorMsg()
202 {
203         switch (g_errorCode)
204         {
205                 case MULTIPR_APP_NO_ERROR:
206                         return "no error";
207                 
208                 case MULTIPR_APP_UNKNOWN_USAGE:
209                         return "unknown usage";
210                         
211                 case MULTIPR_APP_WRONG_NUMBER_OF_ARGUMENTS:
212                         return "wrong number of arguments";
213                 
214                 case MULTIPR_APP_ILLEGAL_ARGUMENT:
215                         return "illegal argument";
216                 
217                 case MULTIPR_APP_FILE_NOT_FOUND:
218                         return "file not found";
219                         
220                 case MULTIPR_APP_IO_ERROR:
221                         return "i/o error";
222                         
223                 default:
224                         return "error (undefined)";
225         }
226 }
227
228
229 /**
230  * \fn     void parseCommandLine(int argc, char** argv)
231  * \brief  parses the command line and configure this application.
232  * \param  argc number of arguments.
233  * \param  argv array of arguments.
234  */
235 void parseCommandLine(int argc, char** argv)
236 {
237         if (argc == 1)
238         {
239                 g_usage = MULTIPR_USAGE_UNKNOWN; 
240                 return;
241         }
242         
243         if (strcmp(argv[1],"--help") == 0)
244         {
245                 g_usage = MULTIPR_USAGE_DISPLAY_HELP;
246         }
247         else if (strcmp(argv[1],"--auto") == 0)
248         {
249                 if (argc != 3)
250                 {
251                         g_usage = MULTIPR_USAGE_UNKNOWN; 
252                         g_errorCode = MULTIPR_APP_WRONG_NUMBER_OF_ARGUMENTS;
253                 }
254                 else
255                 {
256                         g_usage = MULTIPR_USAGE_AUTOTEST;
257                         g_medFilename = argv[2];
258                 }
259         }
260         else if (strcmp(argv[1],"--part1") == 0)
261         {
262                 if (argc != 4)
263                 {
264                         g_usage = MULTIPR_USAGE_UNKNOWN; 
265                         g_errorCode = MULTIPR_APP_WRONG_NUMBER_OF_ARGUMENTS;
266                 }
267                 else
268                 {
269                         g_usage       = MULTIPR_USAGE_PARTITION1;
270                         g_medFilename = argv[2];
271                         g_meshName    = argv[3];
272                 }
273         }
274         else if (strcmp(argv[1],"--part2") == 0)
275         {
276                 if ((argc != 5) && (argc != 6))
277                 {
278                         g_usage = MULTIPR_USAGE_UNKNOWN; 
279                         g_errorCode = MULTIPR_APP_WRONG_NUMBER_OF_ARGUMENTS;
280                 }
281                 else
282                 {
283                         g_usage       = MULTIPR_USAGE_PARTITION2; 
284                         g_medFilename = argv[2];
285                         g_partName    = argv[3];
286                         g_nbParts     = atoi(argv[4]);
287                         
288                         if (argc == 6)
289                         {
290                                 g_splitter = atoi(argv[5]);
291                         }
292                 }
293         }
294         else if (strcmp(argv[1],"--decim") == 0)
295         {
296                 if ((argc != 10) && (argc != 11))
297                 {
298                         g_usage = MULTIPR_USAGE_UNKNOWN; 
299                         g_errorCode = MULTIPR_APP_WRONG_NUMBER_OF_ARGUMENTS;
300                 }
301                 else
302                 {
303                         g_usage               = MULTIPR_USAGE_DECIMATION; 
304                         g_medFilename         = argv[2];
305                         g_partName            = argv[3];
306                         g_fieldName           = argv[4];
307                         g_fieldTimeStepIt     = atoi(argv[5]);
308                         g_filterName          = argv[6];
309                         g_decimThresholdMed   = atof(argv[7]);
310                         g_decimThresholdLow   = atof(argv[8]);
311                         g_decimRadius         = atof(argv[9]);
312                         
313                         if (argc == 11)
314                         {
315                                 g_boxing      = atoi(argv[10]);
316                         }
317                 }
318         }
319         else if (strcmp(argv[1],"--info") == 0)
320         {
321                 if ((argc != 3) && (argc != 4))
322                 {
323                         g_usage = MULTIPR_USAGE_UNKNOWN; 
324                         g_errorCode = MULTIPR_APP_WRONG_NUMBER_OF_ARGUMENTS;
325                 }
326                 else
327                 {
328                         g_usage               = MULTIPR_USAGE_INFO; 
329                         g_medFilename         = argv[2];
330                         
331                         if (argc == 4)
332                         {
333                                 g_meshName    = argv[3];
334                         }
335                 }
336         }
337         else
338         {
339                 g_usage = MULTIPR_USAGE_UNKNOWN;
340                 g_errorCode = MULTIPR_APP_UNKNOWN_USAGE;
341         }
342 }
343
344
345 /**
346  * \fn     int runAutotest()
347  * \brief  performs some unit tests on the MULTIPR API. 
348  * \return MULTIPR_APP_OK if successful, MULTIPR_APP_FAILED if failure.
349  */
350 int runAutotest()
351 {
352         cout << "Start autotest..." << endl;
353         
354         int ret = MULTIPR_APP_OK;
355         try
356         {
357                 string strMEDfilename = g_medFilename;
358                 strMEDfilename += "/agregat100grains_12pas.med";
359                 
360                 cout << "Test file: " << strMEDfilename << endl << endl;
361                 
362                 //---------------------------------------------------------------------
363                 // Test partionneDomaine() = extract groups from a sequential MED file
364                 //---------------------------------------------------------------------
365                 multipr::partitionneDomaine(strMEDfilename.c_str(), "MAIL"); 
366                 
367                 //---------------------------------------------------------------------
368                 // Test partitionneGrain() = split a group from a distributed MED file
369                 // using MEDSPLITTER (METIS)
370                 //---------------------------------------------------------------------
371                 string strDistributedMEDfilename = g_medFilename;
372                 strDistributedMEDfilename += "/agregat100grains_12pas_grains_maitre.med";
373                 
374                 multipr::partitionneGrain(
375                         strDistributedMEDfilename.c_str(), 
376                         "MAIL_1", 
377                         4, 
378                         multipr::MULTIPR_SCOTCH);
379                         
380                 multipr::partitionneGrain(
381                         strDistributedMEDfilename.c_str(), 
382                         "MAIL_97", 
383                         3, 
384                         multipr::MULTIPR_METIS);
385
386                 //---------------------------------------------------------------------
387                 // Test decimePartition() = generate 2 lower resolution of a mesh
388                 // using decimation based on gradient
389                 //---------------------------------------------------------------------
390                 multipr::decimePartition(
391                         strDistributedMEDfilename.c_str(), 
392                         "MAIL_98",
393                         "SIG_____SIEF_ELGA_______________",
394                         12,
395                         "Filtre_GradientMoyen",
396                         10.0,
397                         25.0,
398                         0.3,
399                         100);
400                         
401                 multipr::decimePartition(
402                         strDistributedMEDfilename.c_str(), 
403                         "MAIL_92",
404                         "SIG_____SIEF_ELGA_______________",
405                         11,
406                         "Filtre_GradientMoyen",
407                         10.0,
408                         25.0,
409                         0.5,
410                         10);
411                 
412                 multipr::decimePartition(
413                         strDistributedMEDfilename.c_str(), 
414                         "MAIL_97_2",
415                         "SIG_____SIEF_ELGA_______________",
416                         10,
417                         "Filtre_GradientMoyen",
418                         10.0,
419                         25.0,
420                         0.4,
421                         20);
422                         
423                 //---------------------------------------------------------------------
424                 // Test passed: OK!
425                 //---------------------------------------------------------------------
426                 cout << endl;
427                 cout << "Test passed: everything seems to be OK" << endl;
428                 cout << "OK" << endl << endl;
429                 
430         }
431         catch (multipr::RuntimeException& e)
432         {
433                 e.dump(cout);
434                 cout << endl;
435                 cout << "Test failed" << endl;
436                 cout << "Failure" << endl << endl;
437                 ret = MULTIPR_APP_FAILED;
438         }
439         
440         return ret;
441 }
442
443
444 /**
445  * \fn     void runPartition1()
446  * \brief  builds a distributed MED file (v2.3) by extracting groups from a sequential MED file. 
447  * \return MULTIPR_APP_OK if successful, MULTIPR_APP_FAILED if failure.
448  */
449 int runPartition1()
450 {
451         int ret = MULTIPR_APP_OK;
452         try
453         {
454                 multipr::partitionneDomaine(g_medFilename, g_meshName); 
455         }
456         catch (multipr::RuntimeException& e)
457         {
458                 e.dump(cout);
459                 ret = MULTIPR_APP_FAILED;
460         }
461                 
462         return ret;
463 }
464
465
466 /**
467  * \fn     void runPartition2()
468  * \brief  builds a distributed MED file (v2.3) by splitting a part of a distributed MED file generated by runPartition1().  
469  * \return MULTIPR_APP_OK if successful, MULTIPR_APP_FAILED if failure.
470  */
471 int runPartition2()
472 {       
473         int ret = MULTIPR_APP_OK;
474         try
475         {
476                 multipr::partitionneGrain(
477                         g_medFilename, 
478                         g_partName, 
479                         g_nbParts, 
480                         g_splitter);
481         }
482         catch (multipr::RuntimeException& e)
483         {
484                 e.dump(cout);
485                 ret = MULTIPR_APP_FAILED;
486         }
487                 
488         return ret;
489 }
490
491
492 /**
493  * \fn     int runDecimation()
494  * \brief  creates 3 resolutions of a part of a distributed MED file. 
495  * \return MULTIPR_APP_OK if successful, MULTIPR_APP_FAILED if failure.
496  */
497 int runDecimation()
498 {       
499         int ret = MULTIPR_APP_OK;
500         try
501         {
502                 multipr::decimePartition(
503                         g_medFilename, 
504                         g_partName,
505                         g_fieldName,
506                         g_fieldTimeStepIt,
507                         g_filterName,
508                         g_decimThresholdMed,
509                         g_decimThresholdLow,
510                         g_decimRadius,
511                         g_boxing);
512         }
513         catch (multipr::RuntimeException& e)
514         {
515                 e.dump(cout);
516                 ret = MULTIPR_APP_FAILED;
517         }
518                 
519         return ret;
520 }
521
522
523 /**
524  * \fn     int runDumpMED()
525  * \brief  dumps info about a sequential MED file.
526  * \return MULTIPR_APP_OK if successful, MULTIPR_APP_FAILED if failure.
527  */
528 int runDumpMED()
529 {
530 #ifdef MULTIPR_USE_OBJ_API
531         int ret = MULTIPR_APP_OK;
532         try
533         {
534                 // if mesh is unknown, then list all the meshes in the given MED file
535                 if (g_meshName == NULL)
536                 {
537                         multipr::Obj obj;
538                         obj.create(g_medFilename);
539                         
540                         {
541                                 // display list of meshes contained in the MED file
542                                 vector<string> res = obj.getMeshes();
543                                 cout << "List of meshes in this MED file:" << endl;
544                                 for (unsigned i = 0 ; i < res.size() ; i++)
545                                 {
546                                         cout << "Mesh " << (i + 1) << ": " << res[i] << endl;
547                                 }
548                         }
549                         
550                         cout << endl;
551                         
552                         {
553                                 // display list of fields contained in the MED file
554                                 vector<string> names = obj.getFields();
555                                 cout << "List of fields in this MED file:" << endl;
556                                 for (unsigned i = 0 ; i < names.size() ; i++)
557                                 {
558                                         cout << "Field " << (i + 1) << ": " << names[i] << " #it=" << obj.getTimeStamps(names[i].c_str()) << endl;
559                                 }
560                         }
561                 }
562                 else
563                 {
564                         // display all infos about one mesh in a MED file
565                         multipr::Mesh mesh;
566                         mesh.readSequentialMED(g_medFilename, g_meshName);
567                         mesh.setPrintAll(true);
568                         cout << mesh << endl;
569                 }
570                 cout << "OK" << endl;
571         }
572         catch (multipr::RuntimeException& e)
573         {
574                 e.dump(cout);
575                 ret = MULTIPR_APP_FAILED;
576         }
577         
578         return ret;
579 #else
580         int ret = MULTIPR_APP_OK;
581         try
582         {
583                 // if mesh is unknown, then list all the meshes in the given MED file
584                 if (g_meshName == NULL)
585                 {
586                         {
587                                 // display list of meshes contained in the MED file
588                                 vector<string> res = multipr::getListMeshes(g_medFilename);
589                                 cout << "List of meshes in this MED file:" << endl;
590                                 for (unsigned i = 0 ; i < res.size() ; i++)
591                                 {
592                                         cout << "Mesh " << (i + 1) << ": " << res[i] << endl;
593                                 }
594                         }
595                         
596                         cout << endl;
597                         
598                         {
599                                 // display list of fields contained in the MED file
600                                 vector<pair<string,int> > res = multipr::getListScalarFields(g_medFilename);
601                                 cout << "List of fields in this MED file:" << endl;
602                                 for (unsigned i = 0 ; i < res.size() ; i++)
603                                 {
604                                         cout << "Field " << (i + 1) << ": " << res[i].first << " #it=" << res[i].second << endl;
605                                 }
606                         }
607                 }
608                 else
609                 {
610                         // display all infos about one mesh in a MED file
611                         multipr::Mesh mesh;
612                         mesh.readSequentialMED(g_medFilename, g_meshName);
613                         mesh.setPrintAll(true);
614                         cout << mesh << endl;
615                 }
616                 cout << "OK" << endl;
617         }
618         catch (multipr::RuntimeException& e)
619         {
620                 e.dump(cout);
621                 ret = MULTIPR_APP_FAILED;
622         }
623         
624         return ret;
625 #endif
626 }
627
628
629 /**
630  * \fn     int run()
631  * \brief  applies partitioning/decimation according to global parameters.
632  * \return MULTIPR_APP_OK if successful, MULTIPR_APP_FAILED if failure.
633  */
634 int run()
635 {
636         printGlobals();
637
638         int ret = MULTIPR_APP_OK;
639         switch (g_usage)
640         {
641                 case MULTIPR_USAGE_AUTOTEST:   ret = runAutotest();   break;
642                 case MULTIPR_USAGE_PARTITION1: ret = runPartition1(); break;
643                 case MULTIPR_USAGE_PARTITION2: ret = runPartition2(); break;
644                 case MULTIPR_USAGE_DECIMATION: ret = runDecimation(); break;
645                 case MULTIPR_USAGE_INFO:       ret = runDumpMED();    break;
646                 default:
647                         cout << "ERROR: unknown usage" << endl;
648                         ret = MULTIPR_APP_FAILED;
649                         break;
650         }
651         
652         return ret;
653 }
654
655
656 /**
657  * \fn     int main(int argc, char** argv)
658  * \brief  entry point of the application.
659  * \param  argc number of arguments.
660  * \param  argv list of arguments.
661  * \return 0 if OK, 1 if failed.
662  */
663 int main(int argc, char** argv)
664 {
665         cout << "multipr v" << multipr::getVersion() << " - by EDF/CS - 01/2007" << endl;
666         cout << "==================================" << endl;
667         
668         #ifdef MULTIPR_USE_OBJ_API
669                 cout << "Version MULTIPR_Obj" << endl;
670         #else
671                 cout << "Version MULTIPR_API" << endl;
672         #endif   
673
674         parseCommandLine(argc, argv);
675
676         int ret = MULTIPR_APP_OK; // assume no error at the beginning
677         
678         if (g_usage == MULTIPR_USAGE_UNKNOWN)
679         {
680                 if (argc != 1)
681                 {
682                         // if usage is unknown and there are some arguments, print an error message 
683                         cout << "ERROR: " << getErrorMsg() << endl;
684                         cout << endl;
685                         ret = MULTIPR_APP_FAILED;
686                 }
687                 else
688                 {
689                         // if no argument, print a description of this application
690                         printDescription();
691                 }
692
693                 printUsage();
694         }
695         else if (g_usage == MULTIPR_USAGE_DISPLAY_HELP)
696         {
697                 printDescription();
698                 printUsage();
699         }
700         else
701         {
702                 // the application seems to be configured properly: it can be executed
703                 ret = run();
704         }
705         
706         return ret;
707 }
708
709 // EOF