Salome HOME
updated copyright message
[plugins/ghs3dplugin.git] / src / GHS3DPlugin / GHS3DPlugin_Hypothesis.cxx
1 // Copyright (C) 2004-2023  CEA, EDF
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 //=============================================================================
21 // File      : GHS3DPlugin_Hypothesis.cxx
22 // Created   : Wed Apr  2 12:36:29 2008
23 // Author    : Edward AGAPOV (eap)
24 //=============================================================================
25 //
26 #include "GHS3DPlugin_Hypothesis.hxx"
27
28 #include <Basics_DirUtils.hxx>
29 #include <SMESHDS_Mesh.hxx>
30 #include <SMESH_File.hxx>
31
32 #include <TCollection_AsciiString.hxx>
33
34 #ifdef WIN32
35 #include <process.h>
36 #define getpid _getpid
37 #endif
38
39 using namespace std;
40
41 namespace
42 {
43   struct GET_DEFAULT // struct used to get default value from GetOptionValue()
44   {
45     bool isDefault;
46     operator bool* () { return &isDefault; }
47   };
48 }
49
50 //=======================================================================
51 //function : GHS3DPlugin_Hypothesis
52 //=======================================================================
53
54 GHS3DPlugin_Hypothesis::GHS3DPlugin_Hypothesis(int hypId, SMESH_Gen * gen)
55   : SMESH_Hypothesis(hypId, gen),
56     myToMeshHoles(DefaultMeshHoles()),
57     myToMakeGroupsOfDomains(DefaultToMakeGroupsOfDomains()),
58     myMaximumMemory(-1),
59     myInitialMemory(-1),
60     myOptimizationLevel(DefaultOptimizationLevel()),
61     myKeepFiles(DefaultKeepFiles()),
62     myWorkingDirectory(DefaultWorkingDirectory()),
63     myVerboseLevel(DefaultVerboseLevel()),
64     myToCreateNewNodes(DefaultToCreateNewNodes()),
65     myToUseBoundaryRecoveryVersion(DefaultToUseBoundaryRecoveryVersion()),
66     myToUseFemCorrection(DefaultToUseFEMCorrection()),
67     myToRemoveCentralPoint(DefaultToRemoveCentralPoint()),
68     myLogInStandardOutput(DefaultStandardOutputLog()),
69     myRemoveLogOnSuccess( DefaultRemoveLogOnSuccess() ),
70     myGradation(DefaultGradation()),
71     myUseVolumeProximity(DefaultUseVolumeProximity()),
72     myNbVolumeProximityLayers(DefaultNbVolumeProximityLayers()),
73     myAlgorithm(DefaultAlgorithm()),    
74     myNumOfThreads(DefaultNumOfThreads()),
75     myUseNumOfThreads(DefaultUseNumOfThreads()),
76     myPthreadModeMG(DefaultMyPthreadMode()),
77     myPthreadModeMGHPC(DefaultMyPthreadModeHPC()),
78     myMinSize(0),
79     myMinSizeDefault(0),
80     myMaxSize(0),
81     myMaxSizeDefault(0)
82 {
83   _name = GetHypType();
84   _param_algo_dim = 3;
85
86   const char* boolOptionNames[] = { "no_initial_central_point",                          // no
87                                     "force_max_size",                                    // no
88                                     "apply_gradation_on_skin_vertex_sizes",              // yes
89                                     "optimise_worst_elements",                           // no
90                                     "force_output_quadratic_mesh",                       // no
91                                     "rectify_jacobian",                                  // yes
92                                     "jacobian_rectification_respect_input_surface_mesh", // yes
93                                     "" // mark of end
94   };
95   const char* intOptionNames[] = { "max_number_of_errors_printed", // 1
96                                    "" // mark of end
97   };
98   const char* doubleOptionNames[] = { "target_quality",  // 0
99                                       "sliver_angle",    // 5
100                                       "" // mark of end
101   };
102   const char* charOptionNames[] = { "boundary_regeneration",            // standard
103                                     "split_overconstrained_tetrahedra", // no
104                                     "" // mark of end
105   };
106
107   int i = 0;
108   while (boolOptionNames[i][0])
109   {
110     _boolOptions.insert( boolOptionNames[i] );
111     _option2value[boolOptionNames[i++]].clear();
112   }
113   i = 0;
114   while (intOptionNames[i][0])
115     _option2value[intOptionNames[i++]].clear();
116   
117   i = 0;
118   while (doubleOptionNames[i][0]) {
119     _doubleOptions.insert(doubleOptionNames[i]);
120     _option2value[doubleOptionNames[i++]].clear();
121   }
122   i = 0;
123   while (charOptionNames[i][0]) {
124     _charOptions.insert(charOptionNames[i]);
125     _option2value[charOptionNames[i++]].clear();
126   }
127
128   // default values to be used while MG meshing
129
130   _defaultOptionValues["no_initial_central_point"                         ] = "no";
131   _defaultOptionValues["force_max_size"                                   ] = "no";
132   _defaultOptionValues["apply_gradation_on_skin_vertex_sizes"             ] = "yes";
133   _defaultOptionValues["optimise_worst_elements"                          ] = "no";
134   _defaultOptionValues["force_output_quadratic_mesh"                      ] = "no";
135   _defaultOptionValues["rectify_jacobian"                                 ] = "yes";
136   _defaultOptionValues["jacobian_rectification_respect_input_surface_mesh"] = "yes";
137   _defaultOptionValues["max_number_of_errors_printed"                     ] = "1";
138   _defaultOptionValues["target_quality"                                   ] = "";//NoValue();
139   _defaultOptionValues["sliver_angle"                                     ] = "5";
140   _defaultOptionValues["boundary_regeneration"                            ] = "standard";
141   _defaultOptionValues["split_overconstrained_tetrahedra"                 ] = "no";
142
143 #ifdef _DEBUG_
144   // check validity of option names of _defaultOptionValues
145   TOptionValues::iterator n2v = _defaultOptionValues.begin();
146   for ( ; n2v != _defaultOptionValues.end(); ++n2v )
147     ASSERT( _option2value.count( n2v->first ));
148   ASSERT( _option2value.size() == _defaultOptionValues.size() );
149 #endif
150 }
151
152 //=======================================================================
153 //function : SetToMeshHoles
154 //=======================================================================
155
156 void GHS3DPlugin_Hypothesis::SetToMeshHoles(bool toMesh)
157 {
158   if ( myToMeshHoles != toMesh ) {
159     myToMeshHoles = toMesh;
160     NotifySubMeshesHypothesisModification();
161   }
162 }
163
164 //=======================================================================
165 //function : GetToMeshHoles
166 //=======================================================================
167
168 bool GHS3DPlugin_Hypothesis::GetToMeshHoles(bool checkFreeOption) const
169 {
170   if ( checkFreeOption )
171   {
172     std::string optionName = "components";
173     TOptionValues::const_iterator op_val = _customOption2value.find(optionName);
174     if ( op_val != _customOption2value.end())
175     {
176       if ( op_val->second.find("all"))
177         return true;
178       if ( op_val->second.find("outside_components"))
179         return false;
180     }
181   }
182   return myToMeshHoles;
183 }
184
185 //=======================================================================
186 //function : SetToMakeGroupsOfDomains
187 //=======================================================================
188
189 void GHS3DPlugin_Hypothesis::SetToMakeGroupsOfDomains(bool toMakeGroups)
190 {
191   if ( myToMakeGroupsOfDomains != toMakeGroups ) {
192     myToMakeGroupsOfDomains = toMakeGroups;
193     NotifySubMeshesHypothesisModification();
194   }
195 }
196
197 //=======================================================================
198 //function : GetToMakeGroupsOfDomains
199 //=======================================================================
200
201 bool GHS3DPlugin_Hypothesis::GetToMakeGroupsOfDomains() const
202 {
203   return myToMakeGroupsOfDomains;
204 }
205
206 //=======================================================================
207 //function : GetToMakeGroupsOfDomains
208 //=======================================================================
209
210 bool GHS3DPlugin_Hypothesis::GetToMakeGroupsOfDomains(const GHS3DPlugin_Hypothesis* hyp)
211 {
212   bool res;
213   if ( hyp ) res = /*hyp->GetToMeshHoles(true) &&*/ hyp->GetToMakeGroupsOfDomains();
214   else       res = /*DefaultMeshHoles()        &&*/ DefaultToMakeGroupsOfDomains();
215   return res;
216 }
217
218 //=======================================================================
219 //function : SetMaximumMemory
220 //=======================================================================
221
222 void GHS3DPlugin_Hypothesis::SetMaximumMemory(float MB)
223 {
224   if ( myMaximumMemory != MB ) {
225     myMaximumMemory = MB;
226     NotifySubMeshesHypothesisModification();
227   }
228 }
229
230 //=======================================================================
231 //function : GetMaximumMemory
232 //           * automatic memory adjustment mode. Default is zero
233 //=======================================================================
234
235 float GHS3DPlugin_Hypothesis::GetMaximumMemory() const
236 {
237   return myMaximumMemory;
238 }
239
240 //=======================================================================
241 //function : SetInitialMemory
242 //=======================================================================
243
244 void GHS3DPlugin_Hypothesis::SetInitialMemory(float MB)
245 {
246   if ( myInitialMemory != MB ) {
247     myInitialMemory = MB;
248     NotifySubMeshesHypothesisModification();
249   }
250 }
251
252 //=======================================================================
253 //function : GetInitialMemory
254 //=======================================================================
255
256 float GHS3DPlugin_Hypothesis::GetInitialMemory() const
257 {
258   return myInitialMemory;
259 }
260
261 //=======================================================================
262 //function : SetOptimizationLevel
263 //=======================================================================
264
265 void GHS3DPlugin_Hypothesis::SetOptimizationLevel(OptimizationLevel level)
266 {
267   if ( myOptimizationLevel != level ) {
268     myOptimizationLevel = level;
269     NotifySubMeshesHypothesisModification();
270   }
271 }
272
273 //=======================================================================
274 //function : GetOptimizationLevel
275 //=======================================================================
276
277 GHS3DPlugin_Hypothesis::OptimizationLevel GHS3DPlugin_Hypothesis::GetOptimizationLevel() const
278 {
279   return (OptimizationLevel) myOptimizationLevel;
280 }
281
282 //=======================================================================
283 //function : SetWorkingDirectory
284 //=======================================================================
285
286 void GHS3DPlugin_Hypothesis::SetWorkingDirectory(const std::string& path)
287 {
288   if ( myWorkingDirectory != path ) {
289     myWorkingDirectory = path;
290     NotifySubMeshesHypothesisModification();
291   }
292 }
293
294 //=======================================================================
295 //function : GetWorkingDirectory
296 //=======================================================================
297
298 std::string GHS3DPlugin_Hypothesis::GetWorkingDirectory() const
299 {
300   return myWorkingDirectory;
301 }
302
303 //=======================================================================
304 //function : SetKeepFiles
305 //=======================================================================
306
307 void GHS3DPlugin_Hypothesis::SetKeepFiles(bool toKeep)
308 {
309   if ( myKeepFiles != toKeep ) {
310     myKeepFiles = toKeep;
311     NotifySubMeshesHypothesisModification();
312   }
313 }
314
315 //=======================================================================
316 //function : GetKeepFiles
317 //=======================================================================
318
319 bool GHS3DPlugin_Hypothesis::GetKeepFiles() const
320 {
321   return myKeepFiles;
322 }
323
324 //=======================================================================
325 //function : SetVerboseLevel
326 //=======================================================================
327
328 void GHS3DPlugin_Hypothesis::SetVerboseLevel(short level)
329 {
330   if ( myVerboseLevel != level ) {
331     myVerboseLevel = level;
332     NotifySubMeshesHypothesisModification();
333   }
334 }
335
336 //=======================================================================
337 //function : GetVerboseLevel
338 //=======================================================================
339
340 short GHS3DPlugin_Hypothesis::GetVerboseLevel() const
341 {
342   return myVerboseLevel;
343 }
344
345 //=======================================================================
346 //function : SetToCreateNewNodes
347 //=======================================================================
348
349 void GHS3DPlugin_Hypothesis::SetToCreateNewNodes(bool toCreate)
350 {
351   if ( myToCreateNewNodes != toCreate ) {
352     myToCreateNewNodes = toCreate;
353     NotifySubMeshesHypothesisModification();
354   }
355 }
356
357 //=======================================================================
358 //function : SetAlgorithm
359 //=======================================================================
360 void GHS3DPlugin_Hypothesis::SetAlgorithm(ImplementedAlgorithms algoId)
361 {
362   if ( myAlgorithm != algoId ) {
363     myAlgorithm = algoId;
364     NotifySubMeshesHypothesisModification();
365   }
366 }
367
368 //=======================================================================
369 //function :   short GetAlgorithm() const;
370
371 //=======================================================================
372 GHS3DPlugin_Hypothesis::ImplementedAlgorithms GHS3DPlugin_Hypothesis::GetAlgorithm() const
373 {
374   return (ImplementedAlgorithms) myAlgorithm;
375 }
376
377 //=======================================================================
378 //function : SetPthreadMode
379 //=======================================================================
380 void GHS3DPlugin_Hypothesis::SetPthreadMode(PThreadMode pThreadsMode )
381 {
382   if ( myPthreadModeMG != pThreadsMode ) {
383     myPthreadModeMG = pThreadsMode;
384     NotifySubMeshesHypothesisModification();
385   }
386 }
387
388 //=======================================================================
389 //function :   short GetPthreadMode() const;
390
391 //=======================================================================
392 GHS3DPlugin_Hypothesis::PThreadMode GHS3DPlugin_Hypothesis::GetPthreadMode() const
393 {
394   return (PThreadMode)myPthreadModeMG;
395 }
396
397 //=======================================================================
398 //function : SetParallelMode
399 //=======================================================================
400 void GHS3DPlugin_Hypothesis::SetParallelMode(ParallelMode parallelMode )
401 {
402   if ( myPthreadModeMGHPC != parallelMode ) {
403     myPthreadModeMGHPC = parallelMode;
404     NotifySubMeshesHypothesisModification();
405   }
406 }
407
408 //=======================================================================
409 //function :   short GetParallelMode() const;
410
411 //=======================================================================
412 GHS3DPlugin_Hypothesis::ParallelMode GHS3DPlugin_Hypothesis::GetParallelMode() const
413 {
414   return (ParallelMode)myPthreadModeMGHPC;
415 }
416
417 //=======================================================================
418 //function : SetUseNumOfThreads
419 //=======================================================================
420 void GHS3DPlugin_Hypothesis::SetUseNumOfThreads(bool setUseOfThreads)
421 {
422   if ( myUseNumOfThreads != setUseOfThreads ) {
423     myUseNumOfThreads = setUseOfThreads;
424     NotifySubMeshesHypothesisModification();
425   }
426 }
427
428 //=======================================================================
429 //function :   bool GetUseNumOfThreads() const;
430
431 //=======================================================================
432 bool GHS3DPlugin_Hypothesis::GetUseNumOfThreads() const
433 {
434   return myUseNumOfThreads;
435 }
436
437 //=======================================================================
438 //function : SetNumOfThreads
439 //=======================================================================
440 void GHS3DPlugin_Hypothesis::SetNumOfThreads(short numOfThreads)
441 {
442   if ( myNumOfThreads != numOfThreads ) {
443     myNumOfThreads = numOfThreads;
444     NotifySubMeshesHypothesisModification();
445   }
446 }
447
448 //=======================================================================
449 //function :   short GetUseNumOfThreads() const;
450
451 //=======================================================================
452 short GHS3DPlugin_Hypothesis::GetNumOfThreads() const
453 {
454   return myNumOfThreads;
455 }
456
457 //=======================================================================
458 //function : GetToCreateNewNodes
459 //=======================================================================
460 bool GHS3DPlugin_Hypothesis::GetToCreateNewNodes() const
461 {
462   return myToCreateNewNodes;
463 }
464
465 //=======================================================================
466 //function : SetToUseBoundaryRecoveryVersion
467 //=======================================================================
468
469 void GHS3DPlugin_Hypothesis::SetToUseBoundaryRecoveryVersion(bool toUse)
470 {
471   if ( myToUseBoundaryRecoveryVersion != toUse ) {
472     myToUseBoundaryRecoveryVersion = toUse;
473     NotifySubMeshesHypothesisModification();
474   }
475 }
476
477 //=======================================================================
478 //function : GetToUseBoundaryRecoveryVersion
479 //=======================================================================
480
481 bool GHS3DPlugin_Hypothesis::GetToUseBoundaryRecoveryVersion() const
482 {
483   return myToUseBoundaryRecoveryVersion;
484 }
485
486 //=======================================================================
487 //function : SetFEMCorrection
488 //=======================================================================
489
490 void GHS3DPlugin_Hypothesis::SetFEMCorrection(bool toUseFem)
491 {
492   if ( myToUseFemCorrection != toUseFem ) {
493     myToUseFemCorrection = toUseFem;
494     NotifySubMeshesHypothesisModification();
495   }
496 }
497
498 //=======================================================================
499 //function : GetFEMCorrection
500 //=======================================================================
501
502 bool GHS3DPlugin_Hypothesis::GetFEMCorrection() const
503 {
504   return myToUseFemCorrection;
505 }
506
507 //=======================================================================
508 //function : SetToRemoveCentralPoint
509 //=======================================================================
510
511 void GHS3DPlugin_Hypothesis::SetToRemoveCentralPoint(bool toRemove)
512 {
513   SetOptionValue( "no_initial_central_point", toRemove ? "yes" : "no" );
514   myToRemoveCentralPoint = toRemove;
515 }
516
517 //=======================================================================
518 //function : GetToRemoveCentralPoint
519 //=======================================================================
520
521 bool GHS3DPlugin_Hypothesis::GetToRemoveCentralPoint() const
522 {
523   return myToRemoveCentralPoint;
524 }
525
526 //=======================================================================
527 //function : SetAdvancedOption
528 //=======================================================================
529
530 void GHS3DPlugin_Hypothesis::SetAdvancedOption(const std::string& option)
531 {
532   size_t wsPos = option.find(' ');
533   if ( wsPos == string::npos )
534   {
535     SetOptionValue( option, "" );
536   }
537   else
538   {
539     std::string opt( option, 0, wsPos );
540     std::string val( option, wsPos + 1 );
541     SetOptionValue( opt, val );
542   }
543 }
544
545 //=======================================================================
546 //function : GetAdvancedOption
547 //=======================================================================
548
549 std::string GHS3DPlugin_Hypothesis::GetAdvancedOption() const
550 {
551   SMESH_Comment txt;
552
553   TOptionValues::const_iterator o2v = _option2value.begin();
554   for ( ; o2v != _option2value.end(); ++o2v )
555     if ( !o2v->second.empty() )
556     {
557       if ( !txt.empty() )
558         txt << " ";
559       txt << o2v->first << " " << o2v->second;
560     }
561   for ( o2v = _customOption2value.begin(); o2v != _customOption2value.end(); ++o2v )
562   {
563     if ( !txt.empty() )
564       txt << " ";
565     txt << o2v->first << " " << o2v->second;
566   }
567   return txt;
568 }
569
570 //=======================================================================
571 //function : SetGradation
572 //=======================================================================
573
574 void GHS3DPlugin_Hypothesis::SetGradation(double gradation)
575 {
576   if ( myGradation != gradation ) {
577     myGradation = gradation;
578     NotifySubMeshesHypothesisModification();
579   }
580 }
581
582 //=======================================================================
583 //function : GetGradation
584 //=======================================================================
585
586 double GHS3DPlugin_Hypothesis::GetGradation() const
587 {
588   return myGradation;
589 }
590
591 //=============================================================================
592 void GHS3DPlugin_Hypothesis::SetMinSize(double theMinSize)
593 {
594   if ( theMinSize != myMinSize )
595   {
596     myMinSize = theMinSize;
597     NotifySubMeshesHypothesisModification();
598   }
599 }
600
601 //=============================================================================
602 void GHS3DPlugin_Hypothesis::SetMaxSize(double theMaxSize)
603 {
604   if ( theMaxSize != myMaxSize )
605   {
606     myMaxSize = theMaxSize;
607     NotifySubMeshesHypothesisModification();
608   }
609 }
610
611 //=============================================================================
612 void GHS3DPlugin_Hypothesis::SetUseVolumeProximity( bool toUse )
613 {
614   if ( myUseVolumeProximity != toUse )
615   {
616     myUseVolumeProximity = toUse;
617     NotifySubMeshesHypothesisModification();
618   }
619 }
620
621 //=============================================================================
622 void GHS3DPlugin_Hypothesis::SetNbVolumeProximityLayers( int nbLayers )
623 {
624   if ( myNbVolumeProximityLayers != nbLayers )
625   {
626     myNbVolumeProximityLayers = nbLayers;
627     NotifySubMeshesHypothesisModification();
628   }
629 }
630
631 //=======================================================================
632 //function : SetStandardOutputLog
633 //=======================================================================
634
635 void GHS3DPlugin_Hypothesis::SetStandardOutputLog(bool logInStandardOutput)
636 {
637   if ( myLogInStandardOutput != logInStandardOutput ) {
638     myLogInStandardOutput = logInStandardOutput;
639     NotifySubMeshesHypothesisModification();
640   }
641 }
642
643 //=======================================================================
644 //function : GetStandardOutputLog
645 //=======================================================================
646
647 bool GHS3DPlugin_Hypothesis::GetStandardOutputLog() const
648 {
649   return myLogInStandardOutput;
650 }
651
652 //=======================================================================
653 //function : SetRemoveLogOnSuccess
654 //=======================================================================
655
656 void GHS3DPlugin_Hypothesis::SetRemoveLogOnSuccess(bool removeLogOnSuccess)
657 {
658   if ( myRemoveLogOnSuccess != removeLogOnSuccess ) {
659     myRemoveLogOnSuccess = removeLogOnSuccess;
660     NotifySubMeshesHypothesisModification();
661   }
662 }
663
664 //=======================================================================
665 //function : GetRemoveLogOnSuccess
666 //=======================================================================
667
668 bool GHS3DPlugin_Hypothesis::GetRemoveLogOnSuccess() const
669 {
670   return myRemoveLogOnSuccess;
671 }
672
673 //=======================================================================
674 //function : SetEnforcedVertex
675 //=======================================================================
676
677 bool GHS3DPlugin_Hypothesis::SetEnforcedVertex(std::string theName,
678                                                std::string theEntry,
679                                                std::string theGroupName,
680                                                double      size,
681                                                double x, double y, double z,
682                                                bool        isCompound)
683 {
684   MESSAGE("GHS3DPlugin_Hypothesis::SetEnforcedVertex(\""<< theName << "\", \""<< theEntry << "\", \"" << theGroupName << "\", "
685                                                       << size << ", " << x << ", " << y << ", " << z  << ", "<< isCompound << ")");
686
687   bool toNotify = false;
688   bool toCreate = true;
689
690   TGHS3DEnforcedVertex *oldEnVertex;
691   TGHS3DEnforcedVertex *newEnfVertex = new TGHS3DEnforcedVertex();
692   newEnfVertex->name = theName;
693   newEnfVertex->geomEntry = theEntry;
694   newEnfVertex->coords.clear();
695   if (!isCompound) {
696     newEnfVertex->coords.push_back(x);
697     newEnfVertex->coords.push_back(y);
698     newEnfVertex->coords.push_back(z);
699   }
700   newEnfVertex->groupName = theGroupName;
701   newEnfVertex->size = size;
702   newEnfVertex->isCompound = isCompound;
703   
704   
705   // update _enfVertexList
706   TGHS3DEnforcedVertexList::iterator it = _enfVertexList.find(newEnfVertex);
707   if (it != _enfVertexList.end()) {
708     toCreate = false;
709     oldEnVertex = (*it);
710     MESSAGE("Enforced Vertex was found => Update");
711     if (oldEnVertex->name != theName) {
712       MESSAGE("Update name from \"" << oldEnVertex->name << "\" to \"" << theName << "\"");
713       oldEnVertex->name = theName;
714       toNotify = true;
715     }
716     if (oldEnVertex->groupName != theGroupName) {
717       MESSAGE("Update group name from \"" << oldEnVertex->groupName << "\" to \"" << theGroupName << "\"");
718       oldEnVertex->groupName = theGroupName;
719       toNotify = true;
720     }
721     if (oldEnVertex->size != size) {
722       MESSAGE("Update size from \"" << oldEnVertex->size << "\" to \"" << size << "\"");
723       oldEnVertex->size = size;
724       toNotify = true;
725     }
726     if (toNotify) {
727       // update map coords / enf vertex if needed
728       if (oldEnVertex->coords.size()) {
729         _coordsEnfVertexMap[oldEnVertex->coords] = oldEnVertex;
730         _enfVertexCoordsSizeList[oldEnVertex->coords] = size;
731       }
732
733       // update map geom entry / enf vertex if needed
734       if (oldEnVertex->geomEntry != "") {
735         _geomEntryEnfVertexMap[oldEnVertex->geomEntry] = oldEnVertex;
736         _enfVertexEntrySizeList[oldEnVertex->geomEntry] = size;
737       }
738     }
739   }
740
741 //   //////// CREATE ////////////
742   if (toCreate) {
743     toNotify = true;
744     MESSAGE("Creating new enforced vertex");
745     _enfVertexList.insert(newEnfVertex);
746     if (theEntry == "") {
747       _coordsEnfVertexMap[newEnfVertex->coords] = newEnfVertex;
748       _enfVertexCoordsSizeList[newEnfVertex->coords] = size;
749     }
750     else {
751       _geomEntryEnfVertexMap[newEnfVertex->geomEntry] = newEnfVertex;
752       _enfVertexEntrySizeList[newEnfVertex->geomEntry] = size;
753     }
754   }
755
756   if (toNotify)
757     NotifySubMeshesHypothesisModification();
758
759   MESSAGE("GHS3DPlugin_Hypothesis::SetEnforcedVertex END");
760   return toNotify;
761 }
762
763
764 //=======================================================================
765 //function : SetEnforcedMesh
766 //=======================================================================
767 bool GHS3DPlugin_Hypothesis::SetEnforcedMesh(SMESH_Mesh& theMesh, SMESH::ElementType elementType, std::string name, std::string entry, std::string groupName)
768 {
769   TIDSortedElemSet theElemSet;
770   SMDS_ElemIteratorPtr eIt = theMesh.GetMeshDS()->elementsIterator(SMDSAbs_ElementType(elementType));
771   while ( eIt->more() )
772     theElemSet.insert( eIt->next() );
773   MESSAGE("Add "<<theElemSet.size()<<" types["<<elementType<<"] from source mesh");
774   bool added = SetEnforcedElements( theElemSet, elementType, groupName);
775   if (added) {
776     TGHS3DEnforcedMesh* newEnfMesh = new TGHS3DEnforcedMesh();
777     newEnfMesh->persistID   = theMesh.GetMeshDS()->GetPersistentId();
778     newEnfMesh->name        = name;
779     newEnfMesh->entry       = entry;
780     newEnfMesh->elementType = elementType;
781     newEnfMesh->groupName   = groupName;
782     
783     TGHS3DEnforcedMeshList::iterator it = _enfMeshList.find(newEnfMesh);
784     if (it == _enfMeshList.end()) {
785       _entryEnfMeshMap[entry].insert(newEnfMesh);
786       _enfMeshList.insert(newEnfMesh);
787     }
788     else {
789       delete newEnfMesh;
790     }
791   }
792   return added;
793 }
794
795 //=======================================================================
796 //function : SetEnforcedGroup
797 //=======================================================================
798 bool GHS3DPlugin_Hypothesis::SetEnforcedGroup(const SMESHDS_Mesh* theMeshDS, SMESH::smIdType_array_var theIDs, SMESH::ElementType elementType, std::string name, std::string entry, std::string groupName)
799 {
800   MESSAGE("GHS3DPlugin_Hypothesis::SetEnforcedGroup");
801   TIDSortedElemSet theElemSet;
802     if ( theIDs->length() == 0 ){MESSAGE("The source group is empty");}
803     for ( CORBA::ULong i = 0; i < theIDs->length(); i++) {
804       SMESH::smIdType ind = theIDs[i];
805       if (elementType == SMESH::NODE)
806       {
807         const SMDS_MeshNode * node = theMeshDS->FindNode(ind);
808         if (node)
809           theElemSet.insert( node );
810       }
811       else
812       {
813         const SMDS_MeshElement * elem = theMeshDS->FindElement(ind);
814         if (elem)
815           theElemSet.insert( elem );
816       }
817     }
818
819 //   SMDS_ElemIteratorPtr it = theGroup->GetGroupDS()->GetElements();
820 //   while ( it->more() ) 
821 //     theElemSet.insert( it->next() );
822
823   MESSAGE("Add "<<theElemSet.size()<<" types["<<elementType<<"] from source group ");
824   bool added = SetEnforcedElements( theElemSet, elementType, groupName);
825   if (added) {
826     TGHS3DEnforcedMesh* newEnfMesh = new TGHS3DEnforcedMesh();
827     newEnfMesh->name = name;
828     newEnfMesh->entry = entry;
829     newEnfMesh->elementType = elementType;
830     newEnfMesh->groupName = groupName;
831     
832     TGHS3DEnforcedMeshList::iterator it = _enfMeshList.find(newEnfMesh);
833     if (it == _enfMeshList.end()) {
834       _entryEnfMeshMap[entry].insert(newEnfMesh);
835       _enfMeshList.insert(newEnfMesh);
836     }
837   }
838   return added;
839 }
840
841 //=======================================================================
842 //function : SetEnforcedElements
843 //=======================================================================
844 bool GHS3DPlugin_Hypothesis::SetEnforcedElements(TIDSortedElemSet theElemSet, SMESH::ElementType elementType, std::string groupName)
845 {
846   MESSAGE("GHS3DPlugin_Hypothesis::SetEnforcedElements");
847   TIDSortedElemSet::const_iterator it = theElemSet.begin();
848   const SMDS_MeshElement* elem;
849   const SMDS_MeshNode* node;
850   bool added = true;
851   pair<TIDSortedNodeGroupMap::iterator,bool> nodeRet;
852   pair<TIDSortedElemGroupMap::iterator,bool> elemRet;
853
854   for (;it != theElemSet.end();++it)
855   {
856     elem = (*it);
857     switch (elementType) {
858       case SMESH::NODE:
859         node = dynamic_cast<const SMDS_MeshNode*>(elem);
860         if (node) {
861           nodeRet = _enfNodes.insert(make_pair(node,groupName));
862           added = added && nodeRet.second;
863           string msg = added ? "yes":"no";
864           MESSAGE( "Node (" <<node->X()<<","<<node->Y()<<","<<node->Z()<< ") with ID " << node->GetID() <<" added ? " << msg);
865         }
866         else {
867           SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
868           for (;nodeIt->more();) {
869             node = dynamic_cast<const SMDS_MeshNode*>(nodeIt->next());
870             nodeRet = _enfNodes.insert(make_pair(node,groupName));
871             added = added && nodeRet.second;
872           }
873         }
874         break;
875       case SMESH::EDGE:
876         if (elem->GetType() == SMDSAbs_Edge) {
877           elemRet = _enfEdges.insert(make_pair(elem,groupName));
878           added = added && elemRet.second;
879         }
880         else if (elem->GetType() > SMDSAbs_Edge) {
881           // SMDS_ElemIteratorPtr it = elem->edgesIterator();
882           // for (;it->more();) {
883           //   const SMDS_MeshElement* anEdge = it->next();
884           //   elemRet = _enfEdges.insert(make_pair(anEdge,groupName));
885           //   added = added && elemRet.second;
886           // }
887         }
888         break;
889       case SMESH::FACE:
890         if (elem->GetType() == SMDSAbs_Face)
891         {
892           if (elem->NbCornerNodes() == 3) {
893             elemRet = _enfTriangles.insert(make_pair(elem,groupName));
894             added = added && elemRet.second;
895           }
896         }
897         else if (elem->GetType() > SMDSAbs_Face) { // Group of faces
898           // SMDS_ElemIteratorPtr it = elem->facesIterator();
899           // for (;it->more();) {
900           //   const SMDS_MeshElement* aFace = it->next();
901           //   if (aFace->NbCornerNodes() == 3) {
902           //     elemRet = _enfTriangles.insert(make_pair(aFace,groupName));
903           //     added = added && elemRet.second;
904           //   }
905           // }
906         }
907         break;
908       default:
909         break;
910     };
911   }
912   if (added)
913     NotifySubMeshesHypothesisModification();
914   return added;
915 }
916
917
918 //=======================================================================
919 //function : GetEnforcedVertex
920 //=======================================================================
921
922 GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertex* GHS3DPlugin_Hypothesis::GetEnforcedVertex(double x, double y, double z)
923 {
924   std::vector<double> coord(3);
925   coord[0] = x;
926   coord[1] = y;
927   coord[2] = z;
928   if (_coordsEnfVertexMap.count(coord)>0)
929     return _coordsEnfVertexMap[coord];
930   std::ostringstream msg ;
931   msg << "No enforced vertex at " << x << ", " << y << ", " << z;
932   throw std::invalid_argument(msg.str());
933 }
934
935 GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertex* GHS3DPlugin_Hypothesis::GetEnforcedVertex(const std::string theEntry)
936 {
937   if (_geomEntryEnfVertexMap.count(theEntry)>0)
938     return _geomEntryEnfVertexMap[theEntry];
939   
940   std::ostringstream msg ;
941   msg << "No enforced vertex with entry " << theEntry;
942   throw std::invalid_argument(msg.str());
943 }
944
945 //=======================================================================
946 //function : RemoveEnforcedVertex
947 //=======================================================================
948
949 bool GHS3DPlugin_Hypothesis::RemoveEnforcedVertex(double x, double y, double z, const std::string theEntry)
950 {
951   bool toNotify = false;
952   std::ostringstream msg;
953   TGHS3DEnforcedVertex *oldEnfVertex;
954   std::vector<double> coords(3);
955   coords[0] = x;
956   coords[1] = y;
957   coords[2] = z;
958   
959   // check that enf vertex with given enf vertex entry exists
960   TGeomEntryGHS3DEnforcedVertexMap::iterator it_enfVertexEntry = _geomEntryEnfVertexMap.find(theEntry);
961   if (it_enfVertexEntry != _geomEntryEnfVertexMap.end()) {
962     // Success
963     MESSAGE("Found enforced vertex with geom entry " << theEntry);
964     oldEnfVertex = it_enfVertexEntry->second;
965     _geomEntryEnfVertexMap.erase(it_enfVertexEntry);
966   } else {
967     // Fail
968     MESSAGE("Enforced vertex with geom entry " << theEntry << " not found");
969     // check that enf vertex with given coords exists
970     TCoordsGHS3DEnforcedVertexMap::iterator it_coords_enf = _coordsEnfVertexMap.find(coords);
971     if (it_coords_enf != _coordsEnfVertexMap.end()) {
972       // Success
973       MESSAGE("Found enforced vertex with coords " << x << ", " << y << ", " << z);
974       oldEnfVertex = it_coords_enf->second;
975       _coordsEnfVertexMap.erase(it_coords_enf);
976       _enfVertexCoordsSizeList.erase(_enfVertexCoordsSizeList.find(coords));
977     } else {
978       // Fail
979       MESSAGE("Enforced vertex with coords " << x << ", " << y << ", " << z << " not found");
980       throw std::invalid_argument(msg.str());
981     }
982   }
983
984   MESSAGE("Remove enf vertex from _enfVertexList");
985
986   // update _enfVertexList
987   TGHS3DEnforcedVertexList::iterator it = _enfVertexList.find(oldEnfVertex);
988   if (it != _enfVertexList.end()) {
989     if ((*it)->groupName != "")
990       _groupsToRemove.insert((*it)->groupName);
991     _enfVertexList.erase(it);
992     toNotify = true;
993     MESSAGE("Done");
994   }
995
996   if (toNotify)
997     NotifySubMeshesHypothesisModification();
998
999   return toNotify;
1000 }
1001
1002 //=======================================================================
1003 //function : ClearEnforcedVertices
1004 //=======================================================================
1005 void GHS3DPlugin_Hypothesis::ClearEnforcedVertices()
1006 {
1007   TGHS3DEnforcedVertexList::const_iterator it = _enfVertexList.begin();
1008   for(;it != _enfVertexList.end();++it) {
1009     if ((*it)->groupName != "")
1010       _groupsToRemove.insert((*it)->groupName);
1011   }
1012   _enfVertexList.clear();
1013   _coordsEnfVertexMap.clear();
1014   _geomEntryEnfVertexMap.clear();
1015   _enfVertexCoordsSizeList.clear();
1016   _enfVertexEntrySizeList.clear();
1017   NotifySubMeshesHypothesisModification();
1018 }
1019
1020 //=======================================================================
1021 //function : ClearEnforcedMeshes
1022 //=======================================================================
1023 void GHS3DPlugin_Hypothesis::ClearEnforcedMeshes()
1024 {
1025   TGHS3DEnforcedMeshList::const_iterator it = _enfMeshList.begin();
1026   for(;it != _enfMeshList.end();++it) {
1027     if ((*it)->groupName != "")
1028       _groupsToRemove.insert((*it)->groupName);
1029   }
1030   _enfNodes.clear();
1031   _enfEdges.clear();
1032   _enfTriangles.clear();
1033   _nodeIDToSizeMap.clear();
1034   _enfMeshList.clear();
1035   _entryEnfMeshMap.clear();
1036   NotifySubMeshesHypothesisModification();
1037 }
1038
1039 //================================================================================
1040 /*!
1041  * \brief At mesh loading, restore enforced elements by just loaded enforced meshes
1042  */
1043 //================================================================================
1044
1045 void GHS3DPlugin_Hypothesis::RestoreEnfElemsByMeshes()
1046 {
1047   TGHS3DEnforcedMeshList::const_iterator it = _enfMeshList.begin();
1048   for(;it != _enfMeshList.end();++it) {
1049     TGHS3DEnforcedMesh* enfMesh = *it;
1050     if ( SMESH_Mesh* mesh = GetMeshByPersistentID( enfMesh->persistID ))
1051       SetEnforcedMesh( *mesh,
1052                        enfMesh->elementType,
1053                        enfMesh->name,
1054                        enfMesh->entry,
1055                        enfMesh->groupName );
1056     enfMesh->persistID = -1; // not to restore again
1057   }
1058 }
1059
1060 //=======================================================================
1061 //function : SetGroupsToRemove
1062 //=======================================================================
1063
1064 void GHS3DPlugin_Hypothesis::ClearGroupsToRemove()
1065 {
1066   _groupsToRemove.clear();
1067 }
1068
1069
1070 //=======================================================================
1071 //function : DefaultMeshHoles
1072 //=======================================================================
1073
1074 bool GHS3DPlugin_Hypothesis::DefaultMeshHoles()
1075 {
1076   return false; // PAL19680
1077 }
1078
1079 //=======================================================================
1080 //function : DefaultToMakeGroupsOfDomains
1081 //=======================================================================
1082
1083 bool GHS3DPlugin_Hypothesis::DefaultToMakeGroupsOfDomains()
1084 {
1085   return false; // issue 0022172
1086 }
1087
1088 //=======================================================================
1089 //function : DefaultMaximumMemory
1090 //=======================================================================
1091
1092 #if defined(WIN32)
1093 #include <windows.h>
1094 #elif !defined(__APPLE__)
1095 #include <sys/sysinfo.h>
1096 #endif
1097
1098 float GHS3DPlugin_Hypothesis::DefaultMaximumMemory()
1099 {
1100 #if defined(WIN32)
1101   // See http://msdn.microsoft.com/en-us/library/aa366589.aspx
1102   MEMORYSTATUSEX statex;
1103   statex.dwLength = sizeof (statex);
1104   long err = GlobalMemoryStatusEx (&statex);
1105   if (err != 0) {
1106     double totMB = double( statex.ullAvailPhys ) / 1024. / 1024.;
1107     return float( 0.7 * totMB );
1108   }
1109 #elif !defined(__APPLE__)
1110   struct sysinfo si;
1111   long err = sysinfo( &si );
1112   if ( err == 0 ) {
1113     double ramMB = double( si.totalram * si.mem_unit / 1024 / 1024 );
1114     return float( 0.7 * ramMB );
1115   }
1116 #endif
1117   return 1024;
1118 }
1119
1120 //=======================================================================
1121 //function : DefaultInitialMemory
1122 //=======================================================================
1123
1124 float GHS3DPlugin_Hypothesis::DefaultInitialMemory()
1125 {
1126   return DefaultMaximumMemory();
1127 }
1128
1129 //=======================================================================
1130 //function : DefaultOptimizationLevel
1131 //=======================================================================
1132
1133 short GHS3DPlugin_Hypothesis::DefaultOptimizationLevel()
1134 {
1135   return Medium;
1136 }
1137
1138 //=======================================================================
1139 //function : DefaultWorkingDirectory
1140 //=======================================================================
1141
1142 std::string GHS3DPlugin_Hypothesis::DefaultWorkingDirectory()
1143 {
1144   TCollection_AsciiString aTmpDir;
1145
1146   char *Tmp_dir = getenv("SALOME_TMP_DIR");
1147   if(Tmp_dir != NULL) {
1148     aTmpDir = Tmp_dir;
1149   }
1150   else {
1151 #ifdef WIN32
1152     aTmpDir = TCollection_AsciiString("C:\\");
1153 #else
1154     aTmpDir = TCollection_AsciiString("/tmp/");
1155 #endif
1156   }
1157   return aTmpDir.ToCString();
1158 }
1159
1160 //=======================================================================
1161 //function : DefaultKeepFiles
1162 //=======================================================================
1163
1164 bool   GHS3DPlugin_Hypothesis::DefaultKeepFiles()
1165 {
1166   return false;
1167 }
1168
1169 //=======================================================================
1170 //function : DefaultRemoveLogOnSuccess
1171 //=======================================================================
1172
1173 bool   GHS3DPlugin_Hypothesis::DefaultRemoveLogOnSuccess()
1174 {
1175   return false;
1176 }
1177
1178
1179 //=======================================================================
1180 //function : DefaultVerboseLevel
1181 //=======================================================================
1182
1183 short  GHS3DPlugin_Hypothesis::DefaultVerboseLevel()
1184 {
1185   return 10;
1186 }
1187
1188 //=======================================================================
1189 //function : DefaultToCreateNewNodes
1190 //=======================================================================
1191
1192 bool GHS3DPlugin_Hypothesis::DefaultToCreateNewNodes()
1193 {
1194   return true;
1195 }
1196
1197 //=======================================================================
1198 //function : DefaultToUseBoundaryRecoveryVersion
1199 //=======================================================================
1200
1201 bool GHS3DPlugin_Hypothesis::DefaultToUseBoundaryRecoveryVersion()
1202 {
1203   return false;
1204 }
1205
1206 //=======================================================================
1207 //function : DefaultToUseFEMCorrection
1208 //=======================================================================
1209
1210 bool GHS3DPlugin_Hypothesis::DefaultToUseFEMCorrection()
1211 {
1212   return false;
1213 }
1214
1215 //=======================================================================
1216 //function : DefaultToRemoveCentralPoint
1217 //=======================================================================
1218
1219 bool GHS3DPlugin_Hypothesis::DefaultToRemoveCentralPoint()
1220 {
1221   return false;
1222 }
1223
1224 //=======================================================================
1225 //function : DefaultStandardOutputLog
1226 //=======================================================================
1227
1228 bool GHS3DPlugin_Hypothesis::DefaultStandardOutputLog()
1229 {
1230   return false;
1231 }
1232
1233 // //=======================================================================
1234 // //function : DefaultID2SizeMap
1235 // //=======================================================================
1236 // 
1237 // GHS3DPlugin_Hypothesis::TID2SizeMap GHS3DPlugin_Hypothesis::DefaultID2SizeMap()
1238 // {
1239 //   return GHS3DPlugin_Hypothesis::TID2SizeMap();
1240 // }
1241
1242
1243 //=======================================================================
1244 //function : SaveTo
1245 //=======================================================================
1246
1247 std::ostream & GHS3DPlugin_Hypothesis::SaveTo(std::ostream & save)
1248 {
1249   save << (int) myToMeshHoles                 << " ";
1250   save << myMaximumMemory                     << " ";
1251   save << myInitialMemory                     << " ";
1252   save << myOptimizationLevel                 << " ";
1253   save << myWorkingDirectory                  << " ";
1254   save << (int)myKeepFiles                    << " ";
1255   save << myVerboseLevel                      << " ";
1256   save << (int)myToCreateNewNodes             << " ";
1257   save << (int)myToUseBoundaryRecoveryVersion << " ";
1258   save << (int)myToUseFemCorrection           << " ";
1259   save << (int)myToRemoveCentralPoint         << " ";
1260   save << myGradation                         << " ";
1261   save << myToMakeGroupsOfDomains             << " ";
1262   // if (!myTextOption.empty()) {
1263   //   save << "__OPTIONS_BEGIN__ ";
1264   //   save << myTextOption                      << " ";
1265   //   save << "__OPTIONS_END__ ";
1266   // }
1267   
1268
1269   TGHS3DEnforcedVertexList::iterator it  = _enfVertexList.begin();
1270   if (it != _enfVertexList.end()) {
1271     save << " " << "__ENFORCED_VERTICES_BEGIN__ ";
1272     for ( ; it != _enfVertexList.end(); ++it ) {
1273       TGHS3DEnforcedVertex *enfVertex = (*it);
1274       save << " " << "__BEGIN_VERTEX__";
1275       if (!enfVertex->name.empty()) {
1276         save << " " << "__BEGIN_NAME__";
1277         save << " " << enfVertex->name;
1278         save << " " << "__END_NAME__";
1279       }
1280       if (!enfVertex->geomEntry.empty()) {
1281         save << " " << "__BEGIN_ENTRY__";
1282         save << " " << enfVertex->geomEntry;
1283         save << " " << enfVertex->isCompound;
1284         save << " " << "__END_ENTRY__";
1285       }
1286       if (!enfVertex->groupName.empty()) {
1287         save << " " << "__BEGIN_GROUP__";
1288         save << " " << enfVertex->groupName;
1289         save << " " << "__END_GROUP__";
1290       }
1291       if (enfVertex->coords.size()) {
1292         save << " " << "__BEGIN_COORDS__";
1293         for ( size_t i = 0; i < enfVertex->coords.size(); i++ )
1294           save << " " << enfVertex->coords[i];
1295         save << " " << "__END_COORDS__";
1296       }
1297       save << " " << "__BEGIN_SIZE__";
1298       save << " " << enfVertex->size;
1299       save << " " << "__END_SIZE__";
1300       save << " " << "__END_VERTEX__";
1301     }
1302     save << " " << "__ENFORCED_VERTICES_END__ ";
1303   }
1304
1305   TGHS3DEnforcedMeshList::iterator it_mesh  = _enfMeshList.begin();
1306   if (it_mesh != _enfMeshList.end()) {
1307     save << " " << "__ENFORCED_MESHES_BEGIN__ ";
1308     for ( ; it_mesh != _enfMeshList.end(); ++it_mesh ) {
1309       TGHS3DEnforcedMesh *enfMesh = (*it_mesh);
1310       save << " " << "__BEGIN_ENF_MESH__";
1311
1312       save << " " << "__BEGIN_NAME__";
1313       save << " " << enfMesh->name;
1314       save << " " << "__END_NAME__";
1315
1316       save << " " << "__BEGIN_ENTRY__";
1317       save << " " << enfMesh->entry;
1318       save << " " << "__END_ENTRY__";
1319
1320       save << " " << "__BEGIN_ELEM_TYPE__";
1321       save << " " << (int)enfMesh->elementType;
1322       save << " " << "__END_ELEM_TYPE__";
1323
1324       if (!enfMesh->groupName.empty()) {
1325         save << " " << "__BEGIN_GROUP__";
1326         save << " " << enfMesh->groupName;
1327         save << " " << "__END_GROUP__";
1328       }
1329       save << " " << "__PERSIST_ID__";
1330       save << " " << enfMesh->persistID;
1331       save << " " << "__END_ENF_MESH__";
1332       std::cout << "Saving of enforced mesh " << enfMesh->name.c_str() << " done" << std::endl;
1333     }
1334     save << " "  << "__ENFORCED_MESHES_END__ ";
1335   }
1336
1337   // New options in 2.9.6 (issue #17784)
1338
1339   save << " " << myUseVolumeProximity;
1340   save << " " << myNbVolumeProximityLayers;
1341   save << " " << myMinSize;
1342   save << " " << myMaxSize;
1343   save << " " << myMinSizeDefault;
1344   save << " " << myMaxSizeDefault;
1345
1346   save << " " << _option2value.size();
1347   TOptionValues::iterator o2v = _option2value.begin();
1348   for ( ; o2v != _option2value.end(); ++o2v )
1349     save << " -" << o2v->first << " -" << o2v->second;
1350   
1351   save << " " << _customOption2value.size();
1352   for ( o2v = _customOption2value.begin(); o2v != _customOption2value.end(); ++o2v )
1353     save << " -" << o2v->first << " -" << o2v->second;
1354
1355   // New options (issue #32737) 
1356   save << " " << myAlgorithm;
1357   save << " " << myUseNumOfThreads;
1358   save << " " << myNumOfThreads;
1359   save << " " << myPthreadModeMG;
1360   save << " " << myPthreadModeMGHPC;
1361
1362   return save;
1363 }
1364
1365 //=======================================================================
1366 //function : LoadFrom
1367 //=======================================================================
1368
1369 std::istream & GHS3DPlugin_Hypothesis::LoadFrom(std::istream & load)
1370 {
1371   bool isOK = true;
1372   int i;
1373   double d;
1374
1375   isOK = static_cast<bool>(load >> i);
1376   if (isOK)
1377     myToMeshHoles = i;
1378   else
1379     load.clear(ios::badbit | load.rdstate());
1380
1381   isOK = static_cast<bool>(load >> d);
1382   if (isOK)
1383     myMaximumMemory = float( d );
1384   else
1385     load.clear(ios::badbit | load.rdstate());
1386
1387   isOK = static_cast<bool>(load >> d);
1388   if (isOK)
1389     myInitialMemory = float( d );
1390   else
1391     load.clear(ios::badbit | load.rdstate());
1392
1393   isOK = static_cast<bool>(load >> i);
1394   if (isOK)
1395     myOptimizationLevel = (short int) i;
1396   else
1397     load.clear(ios::badbit | load.rdstate());
1398
1399   isOK = static_cast<bool>(load >> myWorkingDirectory);
1400   if (isOK) {
1401     if ( myWorkingDirectory == "0") { // myWorkingDirectory was empty
1402       myKeepFiles = false;
1403       myWorkingDirectory.clear();
1404     }
1405     else if ( myWorkingDirectory == "1" ) {
1406       myKeepFiles = true;
1407       myWorkingDirectory.clear();
1408     }
1409   }
1410   else
1411     load.clear(ios::badbit | load.rdstate());
1412
1413   if ( !myWorkingDirectory.empty() ) {
1414     isOK = static_cast<bool>(load >> i);
1415     if (isOK)
1416       myKeepFiles = i;
1417     else
1418       load.clear(ios::badbit | load.rdstate());
1419   }
1420
1421   isOK = static_cast<bool>(load >> i);
1422   if (isOK)
1423     myVerboseLevel = (short) i;
1424   else
1425     load.clear(ios::badbit | load.rdstate());
1426
1427   isOK = static_cast<bool>(load >> i);
1428   if (isOK)
1429     myToCreateNewNodes = (bool) i;
1430   else
1431     load.clear(ios::badbit | load.rdstate());
1432
1433   isOK = static_cast<bool>(load >> i);
1434   if (isOK)
1435     myToUseBoundaryRecoveryVersion = (bool) i;
1436   else
1437     load.clear(ios::badbit | load.rdstate());
1438
1439   isOK = static_cast<bool>(load >> i);
1440   if (isOK)
1441     myToUseFemCorrection = (bool) i;
1442   else
1443     load.clear(ios::badbit | load.rdstate());
1444
1445   isOK = static_cast<bool>(load >> i);
1446   if (isOK)
1447     myToRemoveCentralPoint = (bool) i;
1448   else
1449     load.clear(ios::badbit | load.rdstate());
1450
1451   isOK = static_cast<bool>(load >> d);
1452   if (isOK)
1453     myGradation = d;
1454   else
1455     load.clear(ios::badbit | load.rdstate());
1456
1457   std::string separator;
1458   bool hasOptions = false;
1459   bool hasEnforcedVertices = false;
1460   bool hasEnforcedMeshes = false;
1461   isOK = static_cast<bool>(load >> separator);
1462
1463   if ( isOK && ( separator == "0" || separator == "1" ))
1464   {
1465     myToMakeGroupsOfDomains = ( separator == "1" );
1466     isOK = static_cast<bool>(load >> separator);
1467   }
1468
1469   if (isOK) {
1470     if (separator == "__OPTIONS_BEGIN__")
1471       hasOptions = true;
1472     else if (separator == "__ENFORCED_VERTICES_BEGIN__")
1473       hasEnforcedVertices = true;
1474     else if (separator == "__ENFORCED_MESHES_BEGIN__")
1475       hasEnforcedMeshes = true;
1476   }
1477
1478   if (hasOptions) {
1479     std::string txt;
1480     while (isOK) {
1481       isOK = static_cast<bool>(load >> txt);
1482       if (isOK) {
1483         if (txt == "__OPTIONS_END__") {
1484           // if (!myTextOption.empty()) {
1485           //   // Remove last space
1486           //   myTextOption.erase(myTextOption.end()-1);
1487           // }
1488           isOK = false;
1489           break;
1490         }
1491         // myTextOption += txt;
1492         // myTextOption += " ";
1493       }
1494     }
1495   }
1496
1497   if (hasOptions) {
1498     isOK = static_cast<bool>(load >> separator);
1499     if (isOK && separator == "__ENFORCED_VERTICES_BEGIN__")
1500       hasEnforcedVertices = true;
1501     if (isOK && separator == "__ENFORCED_MESHES_BEGIN__")
1502       hasEnforcedMeshes = true;
1503   }
1504
1505   if (hasEnforcedVertices) {
1506     std::string txt, name, entry, groupName;
1507     double size, coords[3];
1508     bool isCompound;
1509     bool hasCoords = false;
1510     isOK = static_cast<bool>(load >> txt);  // __BEGIN_VERTEX__
1511     while (isOK) {
1512       if (txt == "__ENFORCED_VERTICES_END__") {
1513         //isOK = false;
1514         break;
1515       }
1516       
1517       TGHS3DEnforcedVertex *enfVertex = new TGHS3DEnforcedVertex();
1518       while (isOK) {
1519         isOK = static_cast<bool>(load >> txt);
1520         if (txt == "__END_VERTEX__") {
1521           enfVertex->name = name;
1522           enfVertex->geomEntry = entry;
1523           enfVertex->isCompound = isCompound;
1524           enfVertex->groupName = groupName;
1525           enfVertex->coords.clear();
1526           if (hasCoords)
1527             enfVertex->coords.assign(coords,coords+3);
1528
1529           _enfVertexList.insert(enfVertex);
1530
1531           if (enfVertex->coords.size())
1532             _coordsEnfVertexMap[enfVertex->coords] = enfVertex;
1533           if (!enfVertex->geomEntry.empty())
1534             _geomEntryEnfVertexMap[enfVertex->geomEntry] = enfVertex;
1535
1536           name.clear();
1537           entry.clear();
1538           groupName.clear();
1539           hasCoords = false;
1540           isOK = false;
1541         }
1542
1543         if (txt == "__BEGIN_NAME__") {  // __BEGIN_NAME__
1544           while (isOK && (txt != "__END_NAME__")) {
1545             isOK = static_cast<bool>(load >> txt);
1546             if (txt != "__END_NAME__") {
1547               if (!name.empty())
1548                 name += " ";
1549               name += txt;
1550             }
1551           }
1552           MESSAGE("name: " <<name);
1553         }
1554
1555         if (txt == "__BEGIN_ENTRY__") {  // __BEGIN_ENTRY__
1556           isOK = static_cast<bool>(load >> entry);
1557           isOK = static_cast<bool>(load >> isCompound);
1558           isOK = static_cast<bool>(load >> txt); // __END_ENTRY__
1559           if (txt != "__END_ENTRY__")
1560             throw std::exception();
1561           MESSAGE("entry: " << entry);
1562         }
1563
1564         if (txt == "__BEGIN_GROUP__") {  // __BEGIN_GROUP__
1565           while (isOK && (txt != "__END_GROUP__")) {
1566             isOK = static_cast<bool>(load >> txt);
1567             if (txt != "__END_GROUP__") {
1568               if (!groupName.empty())
1569                 groupName += " ";
1570               groupName += txt;
1571             }
1572           }
1573           MESSAGE("groupName: " << groupName);
1574         }
1575
1576         if (txt == "__BEGIN_COORDS__") {  // __BEGIN_COORDS__
1577           hasCoords = true;
1578           isOK = static_cast<bool>(load >> coords[0] >> coords[1] >> coords[2]);
1579           isOK = static_cast<bool>(load >> txt); // __END_COORDS__
1580           if (txt != "__END_COORDS__")
1581             throw std::exception();
1582           MESSAGE("coords: " << coords[0] <<","<< coords[1] <<","<< coords[2]);
1583         }
1584
1585         if (txt == "__BEGIN_SIZE__") {  // __BEGIN_ENTRY__
1586           isOK = static_cast<bool>(load >> size);
1587           isOK = static_cast<bool>(load >> txt); // __END_ENTRY__
1588           if (txt != "__END_SIZE__") {
1589             throw std::exception();
1590           }
1591           MESSAGE("size: " << size);
1592         }
1593       }
1594       isOK = static_cast<bool>(load >> txt);  // __BEGIN_VERTEX__
1595     }
1596   }
1597
1598   if (hasEnforcedVertices) {
1599     isOK = static_cast<bool>(load >> separator);
1600     if (isOK && separator == "__ENFORCED_MESHES_BEGIN__")
1601       hasEnforcedMeshes = true;
1602   }
1603
1604   if (hasEnforcedMeshes) {
1605     std::string txt, name, entry, groupName;
1606     int elementType = -1, persistID = -1;
1607     isOK = static_cast<bool>(load >> txt);  // __BEGIN_ENF_MESH__
1608     while (isOK) {
1609       //                if (isOK) {
1610       if (txt == "__ENFORCED_MESHES_END__")
1611         isOK = false;
1612
1613       TGHS3DEnforcedMesh *enfMesh = new TGHS3DEnforcedMesh();
1614       while (isOK) {
1615         isOK = static_cast<bool>(load >> txt);
1616         if (txt == "__END_ENF_MESH__") {
1617           enfMesh->name = name;
1618           enfMesh->entry = entry;
1619           enfMesh->elementType = (SMESH::ElementType)elementType;
1620           enfMesh->groupName = groupName;
1621           enfMesh->persistID = persistID;
1622
1623           _enfMeshList.insert(enfMesh);
1624           //std::cout << "Restoring of enforced mesh " <<name  << " done" << std::endl;
1625
1626           name.clear();
1627           entry.clear();
1628           elementType = -1;
1629           groupName.clear();
1630           persistID = -1;
1631           isOK = false;
1632         }
1633
1634         if (txt == "__BEGIN_NAME__") {  // __BEGIN_NAME__
1635           while (isOK && (txt != "__END_NAME__")) {
1636             isOK = static_cast<bool>(load >> txt);
1637             if (txt != "__END_NAME__") {
1638               if (!name.empty())
1639                 name += " ";
1640               name += txt;
1641             }
1642           }
1643           MESSAGE("name: " <<name);
1644         }
1645
1646         if (txt == "__BEGIN_ENTRY__") {  // __BEGIN_ENTRY__
1647           isOK = static_cast<bool>(load >> entry);
1648           isOK = static_cast<bool>(load >> txt); // __END_ENTRY__
1649           if (txt != "__END_ENTRY__")
1650             throw std::exception();
1651           MESSAGE("entry: " << entry);
1652         }
1653
1654         if (txt == "__BEGIN_ELEM_TYPE__") {  // __BEGIN_ELEM_TYPE__
1655           isOK = static_cast<bool>(load >> elementType);
1656           isOK = static_cast<bool>(load >> txt); // __END_ELEM_TYPE__
1657           if (txt != "__END_ELEM_TYPE__")
1658             throw std::exception();
1659           MESSAGE("elementType: " << elementType);
1660         }
1661
1662         if (txt == "__BEGIN_GROUP__") {  // __BEGIN_GROUP__
1663           while (isOK && (txt != "__END_GROUP__")) {
1664             isOK = static_cast<bool>(load >> txt);
1665             if (txt != "__END_GROUP__") {
1666               if (!groupName.empty())
1667                 groupName += " ";
1668               groupName += txt;
1669             }
1670           } // while
1671           MESSAGE("groupName: " << groupName);
1672         } // if
1673
1674         if (txt == "__PERSIST_ID__") {
1675           isOK = static_cast<bool>(load >> persistID);
1676           MESSAGE("persistID: " << persistID);
1677         }
1678         //std::cout << "isOK: " << isOK << std::endl;
1679       } // while
1680       //                } // if
1681       isOK = static_cast<bool>(load >> txt);  // __BEGIN_ENF_MESH__
1682     } // while
1683   } // if
1684
1685   // New options in 2.9.6 (issue #17784)
1686
1687   if ( ! hasOptions && ! hasEnforcedVertices && ! hasEnforcedMeshes )
1688     myUseVolumeProximity = ( separator == "1" );
1689   else if ( static_cast<bool>( load >> i ))
1690     myUseVolumeProximity = (bool) i;
1691
1692   if ( static_cast<bool>( load >> myNbVolumeProximityLayers ))
1693   {
1694     load >> myMinSize;
1695     load >> myMaxSize;
1696     load >> myMinSizeDefault;
1697     load >> myMaxSizeDefault;
1698
1699     std::string option, value;
1700     if ( static_cast<bool>( load >> i ) && i >= 0 )
1701     {
1702       for ( int nbRead = 0; nbRead < i; ++nbRead )
1703       {
1704         load >> option >> value;
1705         _option2value[ std::string( option, 1 )] = std::string( value, 1 );
1706       }
1707     }
1708     if ( static_cast<bool>( load >> i ) && i >= 0 )
1709     {
1710       for ( int nbRead = 0; nbRead < i; ++nbRead )
1711       {
1712         load >> option >> value;
1713         _customOption2value[ std::string( option, 1 )] = std::string( value, 1 );
1714       }
1715     }
1716   }
1717
1718   isOK = static_cast<bool>(load >> i);
1719   if (isOK)
1720     myAlgorithm = (short) i;
1721   else
1722     load.clear(ios::badbit | load.rdstate());
1723   
1724   isOK = static_cast<bool>(load >> i);
1725   if (isOK)
1726     myUseNumOfThreads = (short) i;
1727   else
1728     load.clear(ios::badbit | load.rdstate());
1729   
1730   isOK = static_cast<bool>(load >> i);
1731   if (isOK)
1732     myNumOfThreads = (short) i;
1733   else
1734     load.clear(ios::badbit | load.rdstate());
1735
1736   isOK = static_cast<bool>(load >> i);
1737   if (isOK)
1738     myPthreadModeMG = (short) i;
1739   else
1740     load.clear(ios::badbit | load.rdstate());
1741
1742   isOK = static_cast<bool>(load >> i);
1743   if (isOK)
1744     myPthreadModeMGHPC = (short) i;
1745   else
1746     load.clear(ios::badbit | load.rdstate());
1747
1748   return load;
1749 }
1750
1751 //=======================================================================
1752 //function : SetParametersByMesh
1753 //=======================================================================
1754
1755 bool GHS3DPlugin_Hypothesis::SetParametersByMesh(const SMESH_Mesh* ,const TopoDS_Shape&)
1756 {
1757   return false;
1758 }
1759
1760
1761 //================================================================================
1762 /*!
1763  * \brief Sets myToMakeGroupsOfDomains depending on whether theMesh is on shape or not
1764  */
1765 //================================================================================
1766
1767 bool GHS3DPlugin_Hypothesis::SetParametersByDefaults(const TDefaults&  dflts,
1768                                                      const SMESH_Mesh* /*theMesh*/)
1769 {
1770   myToMakeGroupsOfDomains = ( !dflts._shape || dflts._shape->IsNull() );
1771
1772   double diagonal = dflts._elemLength * _gen->GetBoundaryBoxSegmentation();
1773   myMinSizeDefault = 1e-3 * diagonal;
1774   myMaxSizeDefault = diagonal / 5.;
1775
1776   return true;
1777 }
1778
1779 void GHS3DPlugin_Hypothesis::SetAdvancedOptionsInCommandLine( std::string & cmd ) const
1780 {
1781   std::string option, value;
1782   bool isDefault;
1783   const TOptionValues* options[] = { & this->_option2value, & this->_customOption2value };
1784   for ( int iOp = 0; iOp < 2; ++iOp )
1785   {
1786     TOptionValues::const_iterator o2v = options[iOp]->begin();
1787     for ( ; o2v != options[iOp]->end(); ++o2v )
1788     {
1789       option = o2v->first;
1790       value = this->GetOptionValue( option, &isDefault );
1791
1792       if ( isDefault )
1793         continue;
1794
1795       if ( value.empty() )//value == NoValue() )
1796       {
1797         if ( this->_defaultOptionValues.count( option ))
1798           continue; // non-custom option with no value
1799         //value.clear();
1800       }    
1801
1802       if ( strncmp( "no", option.c_str(), 2 ) == 0 ) // options w/o values: --no_*
1803       {
1804         if ( !value.empty() && ToBool( value ) == false )
1805           continue;
1806         value.clear();
1807       }
1808
1809       if ( option[0] != '-' )
1810         cmd += " --";
1811       else
1812         cmd += " ";
1813       cmd += option + " " + value;
1814     }
1815   }
1816 }
1817
1818 //================================================================================
1819 /*!
1820  * \brief Return command to run MG-Tetra mesher excluding file prefix (-f)
1821  */
1822 //================================================================================
1823 std::string GHS3DPlugin_Hypothesis::CommandToRun(const GHS3DPlugin_Hypothesis* hyp,
1824                                                  const bool                    hasShapeToMesh,
1825                                                  const bool                    forExecutable)
1826 {
1827   GHS3DPlugin_Hypothesis::ImplementedAlgorithms algoId = hyp ? (ImplementedAlgorithms) hyp->myAlgorithm : MGTetra;
1828   std::string cmd = GetExeName( algoId );
1829   
1830   // check if any option is overridden by hyp->myTextOption
1831   bool max_memory     = hyp ? !hyp->HasOptionDefined("max_memory")               : true;
1832   bool auto_memory    = hyp ? !hyp->HasOptionDefined("automatic_memory")         : true;
1833   bool comp           = hyp ? !hyp->HasOptionDefined("components")               : true;
1834   bool optim_level    = hyp ? !hyp->HasOptionDefined("optimisation_level")       : true;
1835   bool no_int_points  = hyp ? !hyp->HasOptionDefined("no_internal_points")       : true;
1836   bool C              = hyp ? !hyp->HasOptionDefined("-C")                       : true;
1837   bool verbose        = hyp ? !hyp->HasOptionDefined("verbose")                  : true;
1838   bool gra            = hyp ? !hyp->HasOptionDefined("-Dcpropa")                 : true;
1839   bool rem            = hyp ? !hyp->HasOptionDefined("no_initial_central_point") : true;
1840   //bool fem            = hyp ? !hyp->HasOptionDefined("-FEM")                     : true;
1841
1842   // if use boundary recovery version, few options are allowed
1843   bool useBndRecovery = !C;
1844   if ( !useBndRecovery && hyp )
1845     useBndRecovery = hyp->myToUseBoundaryRecoveryVersion;
1846
1847   // MG-Tetra needs to know amount of memory it may use (MB).
1848   // Default memory is defined at MG-Tetra installation but it may be not enough,  // so allow to use about all available memory
1849   if ( algoId == MGTetra && max_memory ) {
1850     float aMaximumMemory = hyp ? hyp->myMaximumMemory : -1;
1851     cmd += " --max_memory ";
1852     if ( aMaximumMemory < 0 ) cmd += SMESH_Comment( int( DefaultMaximumMemory() ));
1853     else                      cmd += SMESH_Comment( int( aMaximumMemory ));
1854   }
1855   if (  algoId == MGTetra && ( auto_memory && !useBndRecovery ) ) {
1856     float aInitialMemory = hyp ? hyp->myInitialMemory : -1;
1857     cmd += " --automatic_memory ";
1858     if ( aInitialMemory > 0 ) cmd += SMESH_Comment( int( aInitialMemory ));
1859     else                      cmd += "100";
1860   }
1861
1862   // component to mesh
1863   if ( comp && !useBndRecovery ) {
1864     // We always run MG-Tetra with "to mesh holes'==TRUE (see PAL19680)
1865     if ( hasShapeToMesh )
1866       cmd += " --components all";
1867     else {
1868       bool aToMeshHoles = hyp ? hyp->myToMeshHoles : DefaultMeshHoles();
1869       if ( aToMeshHoles ) cmd += " --components all";
1870       else                cmd += " --components outside_components";
1871     }
1872   }
1873   const bool toCreateNewNodes = ( no_int_points && ( !hyp || hyp->myToCreateNewNodes ));
1874
1875   // optimization level
1876   if ( !toCreateNewNodes ) {
1877     cmd += " --optimisation_level none"; // issue 22608
1878   }
1879   else if ( optim_level && hyp && !useBndRecovery ) {
1880     const char* level[] = { "none" , "light" , "standard" , "standard+" , "strong" };
1881     const short myOpt = hyp->myOptimizationLevel;
1882     
1883     if ( myOpt >= 0 && myOpt < 5 && ( algoId == MGTetra || ( algoId == MGTetraHPC && myOpt != 3 ) ) ) {
1884         cmd += " --optimisation_level ";
1885         cmd += level[ myOpt ];
1886     }    
1887   }
1888
1889   // to create internal nodes
1890   if ( no_int_points && !toCreateNewNodes ) {
1891     if ( forExecutable )
1892       cmd += " --no_internal_points";
1893     else
1894       cmd += " --internalpoints no";
1895   }
1896
1897   if ( hyp ) 
1898   {
1899     // verbose mode
1900     if ( verbose ) {
1901       cmd += " --verbose " + SMESH_Comment( hyp->myVerboseLevel );
1902     }
1903
1904     // to remove initial central point.
1905     if ( rem && hyp->myToRemoveCentralPoint ) {
1906       if ( forExecutable )
1907         cmd += " --no_initial_central_point";
1908       else
1909         cmd += " --centralpoint no";
1910     }
1911
1912     if ( hyp->GetMinSize() > 0 )
1913       cmd += " --min_size " + SMESH_Comment( hyp->GetMinSize() );
1914
1915     if ( hyp->GetMaxSize() > 0 )
1916       cmd += " --max_size " + SMESH_Comment( hyp->GetMaxSize() );
1917
1918     // to define volumic gradation.
1919     if ( gra )
1920       cmd += " --gradation " + SMESH_Comment( hyp->myGradation );
1921
1922     if ( hyp->GetUseNumOfThreads() )
1923     {      
1924       cmd += " --max_number_of_threads "  + SMESH_Comment( hyp->GetNumOfThreads() );
1925       const char* pthreadMode[] = { "none" , "aggressive" , "safe" };
1926       const char* parallelMode[] = { "none", "reproducible_given_max_number_of_threads", "reproducible", "aggressive"  };
1927
1928       if ( algoId == MGTetra && hyp->myPthreadModeMG >= 1 && hyp->myPthreadModeMG < 3 ) {
1929         cmd += " --pthreads_mode ";
1930         cmd += pthreadMode[ hyp->myPthreadModeMG ];
1931       }
1932       else if ( algoId == MGTetraHPC && hyp->myPthreadModeMGHPC >= 1 && hyp->myPthreadModeMGHPC < 4 )
1933       {
1934         cmd += " --parallel_strategy ";
1935         cmd += parallelMode[ hyp->myPthreadModeMGHPC ];
1936       }
1937     }
1938
1939     // proximity
1940     if ( hyp->GetUseVolumeProximity() )
1941     {
1942       cmd += " --volume_proximity_layers " + SMESH_Comment( hyp->GetNbVolumeProximityLayers() );
1943     }
1944     
1945     hyp->SetAdvancedOptionsInCommandLine( cmd );
1946   }
1947
1948 #ifdef WIN32
1949   cmd += " < NUL";
1950 #endif
1951   return cmd;
1952 }
1953
1954 //================================================================================
1955 /*!
1956  * \brief Return a unique file name for MGTetra
1957  */
1958 //================================================================================
1959
1960 std::string GHS3DPlugin_Hypothesis::GetFileName(const GHS3DPlugin_Hypothesis* hyp)
1961 {
1962   std::string aTmpDir = hyp ? hyp->GetWorkingDirectory() : DefaultWorkingDirectory();
1963   if ( !SMESH_File( aTmpDir ).exists() )
1964     aTmpDir = Kernel_Utils::GetTmpDirByPath( aTmpDir );
1965
1966   const char lastChar = *aTmpDir.rbegin();
1967 #ifdef WIN32
1968     if(lastChar != '\\') aTmpDir+='\\';
1969 #else
1970     if(lastChar != '/') aTmpDir+='/';
1971 #endif      
1972
1973   TCollection_AsciiString aGenericName = (char*)aTmpDir.c_str();
1974   aGenericName += "GHS3D_";
1975   aGenericName += getpid();
1976   aGenericName += "_";
1977   aGenericName += Abs((Standard_Integer)(long) aGenericName.ToCString());
1978
1979   return aGenericName.ToCString();
1980 }
1981
1982 //================================================================================
1983 /*!
1984  * \brief Return a unique file name when running MGTetra HPC
1985  */
1986 //================================================================================
1987
1988 std::string GHS3DPlugin_Hypothesis::GetFileNameHPC(const GHS3DPlugin_Hypothesis* hyp)
1989 {
1990   std::string aTmpDir = hyp ? hyp->GetWorkingDirectory() : DefaultWorkingDirectory();
1991   if ( !SMESH_File( aTmpDir ).exists() )
1992     aTmpDir = Kernel_Utils::GetTmpDirByPath( aTmpDir );
1993
1994   const char lastChar = *aTmpDir.rbegin();
1995 #ifdef WIN32
1996     if(lastChar != '\\') aTmpDir+='\\';
1997 #else
1998     if(lastChar != '/') aTmpDir+='/';
1999 #endif      
2000
2001   TCollection_AsciiString aGenericName = (char*)aTmpDir.c_str();
2002   aGenericName += "MGTETRAHPC_";
2003   aGenericName += getpid();
2004   aGenericName += "_";
2005   aGenericName += Abs((Standard_Integer)(long) aGenericName.ToCString());
2006
2007   return aGenericName.ToCString();
2008 }
2009
2010 //================================================================================
2011 /*
2012  * Return the name of executable
2013  */
2014 //================================================================================
2015
2016 std::string GHS3DPlugin_Hypothesis::GetExeName( ImplementedAlgorithms algoId )
2017 {
2018   switch ( algoId )
2019   {
2020     case MGTetra:
2021       return "mg-tetra.exe";
2022     case MGTetraHPC:
2023       return "mg-tetra_hpc.exe";
2024     default:
2025       throw( "Undefined algorithm id: ");
2026   }
2027 }
2028
2029 //================================================================================
2030 /*!
2031 * \brief Return the enforced vertices
2032 */
2033 //================================================================================
2034
2035 GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexList GHS3DPlugin_Hypothesis::GetEnforcedVertices(const GHS3DPlugin_Hypothesis* hyp)
2036 {
2037   return hyp ? hyp->_GetEnforcedVertices(): TGHS3DEnforcedVertexList();
2038 }
2039
2040 GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues GHS3DPlugin_Hypothesis::GetEnforcedVerticesCoordsSize (const GHS3DPlugin_Hypothesis* hyp)
2041 {  
2042   return hyp ? hyp->_GetEnforcedVerticesCoordsSize(): TGHS3DEnforcedVertexCoordsValues();
2043 }
2044
2045 GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexEntryValues GHS3DPlugin_Hypothesis::GetEnforcedVerticesEntrySize (const GHS3DPlugin_Hypothesis* hyp)
2046 {  
2047   return hyp ? hyp->_GetEnforcedVerticesEntrySize(): TGHS3DEnforcedVertexEntryValues();
2048 }
2049
2050 GHS3DPlugin_Hypothesis::TCoordsGHS3DEnforcedVertexMap GHS3DPlugin_Hypothesis::GetEnforcedVerticesByCoords (const GHS3DPlugin_Hypothesis* hyp)
2051 {  
2052   return hyp ? hyp->_GetEnforcedVerticesByCoords(): TCoordsGHS3DEnforcedVertexMap();
2053 }
2054
2055 GHS3DPlugin_Hypothesis::TGeomEntryGHS3DEnforcedVertexMap GHS3DPlugin_Hypothesis::GetEnforcedVerticesByEntry (const GHS3DPlugin_Hypothesis* hyp)
2056 {  
2057   return hyp ? hyp->_GetEnforcedVerticesByEntry(): TGeomEntryGHS3DEnforcedVertexMap();
2058 }
2059
2060 GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap GHS3DPlugin_Hypothesis::GetEnforcedNodes(const GHS3DPlugin_Hypothesis* hyp)
2061 {
2062   return hyp ? hyp->_GetEnforcedNodes():TIDSortedNodeGroupMap();
2063 }
2064
2065 GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap GHS3DPlugin_Hypothesis::GetEnforcedEdges(const GHS3DPlugin_Hypothesis* hyp)
2066 {
2067   return hyp ? hyp->_GetEnforcedEdges():TIDSortedElemGroupMap();
2068 }
2069
2070 GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap GHS3DPlugin_Hypothesis::GetEnforcedTriangles(const GHS3DPlugin_Hypothesis* hyp)
2071 {
2072   return hyp ? hyp->_GetEnforcedTriangles():TIDSortedElemGroupMap();
2073 }
2074
2075 GHS3DPlugin_Hypothesis::TID2SizeMap GHS3DPlugin_Hypothesis::GetNodeIDToSizeMap(const GHS3DPlugin_Hypothesis* hyp)
2076 {
2077   return hyp ? hyp->_GetNodeIDToSizeMap(): TID2SizeMap();
2078 }
2079
2080 GHS3DPlugin_Hypothesis::TSetStrings GHS3DPlugin_Hypothesis::GetGroupsToRemove(const GHS3DPlugin_Hypothesis* hyp)
2081 {
2082   return hyp ? hyp->_GetGroupsToRemove(): TSetStrings();
2083 }
2084
2085
2086 //=============================================================================
2087 void GHS3DPlugin_Hypothesis::SetOptionValue(const std::string& optionName,
2088                                             const std::string& optionValue)
2089 {
2090   TOptionValues::iterator op_val = _option2value.find(optionName);
2091   if (op_val == _option2value.end())
2092   {
2093     op_val = _customOption2value.find( optionName );
2094     if ( op_val != _customOption2value.end() && op_val->second != optionValue )
2095       NotifySubMeshesHypothesisModification();
2096     _customOption2value[ optionName ] = optionValue;
2097     return;
2098   }
2099
2100   if (op_val->second != optionValue)
2101   {
2102     const char* ptr = optionValue.c_str();
2103     // strip white spaces
2104     while (ptr[0] == ' ')
2105       ptr++;
2106     size_t i = strlen(ptr);
2107     while (i != 0 && ptr[i - 1] == ' ')
2108       i--;
2109     // check value type
2110     bool typeOk = true;
2111     std::string typeName;
2112     if (i == 0) {
2113       // empty string
2114     } else if (_charOptions.count(optionName)) {
2115       // do not check strings
2116     } else if (_doubleOptions.count(optionName)) {
2117       // check if value is double
2118       ToDbl(ptr, &typeOk);
2119       typeName = "real";
2120     } else if (_boolOptions.count(optionName)) {
2121       // check if value is bool
2122       ToBool(ptr, &typeOk);
2123       typeName = "bool";
2124     } else {
2125       // check if value is int
2126       ToInt(ptr, &typeOk);
2127       typeName = "integer";
2128     }
2129     if ( typeOk ) // check some specific values ?
2130     {
2131     }
2132     if ( !typeOk )
2133     {
2134       std::string msg = "Advanced option '" + optionName + "' = '" + optionValue + "' but must be " + typeName;
2135       throw std::invalid_argument(msg);
2136     }
2137     std::string value( ptr, i );
2138     if ( _defaultOptionValues[ optionName ] == value )
2139       value.clear();
2140
2141     op_val->second = value;
2142
2143     NotifySubMeshesHypothesisModification();
2144   }
2145 }
2146
2147 //=============================================================================
2148 //! Return option value. If isDefault provided, it can be a default value,
2149 //  then *isDefault == true. If isDefault is not provided, the value will be
2150 //  empty if it equals a default one.
2151 std::string GHS3DPlugin_Hypothesis::GetOptionValue(const std::string& optionName,
2152                                                    bool*              isDefault) const
2153 {
2154   TOptionValues::const_iterator op_val = _option2value.find(optionName);
2155   if (op_val == _option2value.end())
2156   {
2157     op_val = _customOption2value.find(optionName);
2158     if (op_val == _customOption2value.end())
2159     {
2160       std::string msg = "Unknown MG-Tetra option: <" + optionName + ">";
2161       throw std::invalid_argument(msg);
2162     }
2163   }
2164   std::string val = op_val->second;
2165   if ( isDefault ) *isDefault = ( val.empty() );
2166
2167   if ( val.empty() && isDefault )
2168   {
2169     op_val = _defaultOptionValues.find( optionName );
2170     if (op_val != _defaultOptionValues.end())
2171       val = op_val->second;
2172   }
2173   return val;
2174 }
2175
2176
2177 //=============================================================================
2178 bool GHS3DPlugin_Hypothesis::HasOptionDefined( const std::string& optionName ) const
2179 {
2180   bool isDefault = false;
2181   try
2182   {
2183     GetOptionValue( optionName, &isDefault );
2184   }
2185   catch ( std::invalid_argument& )
2186   {
2187     return false;
2188   }
2189   return !isDefault;
2190 }
2191
2192 //=============================================================================
2193 void GHS3DPlugin_Hypothesis::ClearOption(const std::string& optionName)
2194 {
2195   TOptionValues::iterator op_val = _customOption2value.find(optionName);
2196   if (op_val != _customOption2value.end())
2197    _customOption2value.erase(op_val);
2198   else {
2199     op_val = _option2value.find(optionName);
2200     if (op_val != _option2value.end())
2201       op_val->second.clear();
2202   }
2203 }
2204
2205 //=============================================================================
2206 GHS3DPlugin_Hypothesis::TOptionValues GHS3DPlugin_Hypothesis::GetOptionValues() const
2207 {
2208   TOptionValues vals;
2209   TOptionValues::const_iterator op_val = _option2value.begin();
2210   for ( ; op_val != _option2value.end(); ++op_val )
2211     vals.insert( make_pair( op_val->first, GetOptionValue( op_val->first, GET_DEFAULT() )));
2212
2213   return vals;
2214 }
2215
2216 //================================================================================
2217 /*!
2218  * \brief Converts a string to a bool
2219  */
2220 //================================================================================
2221
2222 bool GHS3DPlugin_Hypothesis::ToBool(const std::string& str, bool* isOk )
2223 {
2224   std::string s = str;
2225   if ( isOk ) *isOk = true;
2226
2227   for ( size_t i = 0; i <= s.size(); ++i )
2228     s[i] = (char) tolower( s[i] );
2229
2230   if ( s == "1" || s == "true" || s == "active" || s == "yes" )
2231     return true;
2232
2233   if ( s == "0" || s == "false" || s == "inactive" || s == "no" )
2234     return false;
2235
2236   if ( isOk )
2237     *isOk = false;
2238   else {
2239     std::string msg = "Not a Boolean value:'" + str + "'";
2240     throw std::invalid_argument(msg);
2241   }
2242   return false;
2243 }
2244
2245 //================================================================================
2246 /*!
2247  * \brief Converts a string to a real value
2248  */
2249 //================================================================================
2250
2251 double GHS3DPlugin_Hypothesis::ToDbl(const std::string& str, bool* isOk )
2252 {
2253   if ( str.empty() ) throw std::invalid_argument("Empty value provided");
2254
2255   char * endPtr;
2256   double val = strtod(&str[0], &endPtr);
2257   bool ok = (&str[0] != endPtr);
2258
2259   if ( isOk ) *isOk = ok;
2260
2261   if ( !ok )
2262   {
2263     std::string msg = "Not a real value:'" + str + "'";
2264     throw std::invalid_argument(msg);
2265   }
2266   return val;
2267 }
2268
2269 //================================================================================
2270 /*!
2271  * \brief Converts a string to a integer value
2272  */
2273 //================================================================================
2274
2275 int GHS3DPlugin_Hypothesis::ToInt(const std::string& str, bool* isOk )
2276 {
2277   if ( str.empty() ) throw std::invalid_argument("Empty value provided");
2278
2279   char * endPtr;
2280   int val = (int)strtol( &str[0], &endPtr, 10);
2281   bool ok = (&str[0] != endPtr);
2282
2283   if ( isOk ) *isOk = ok;
2284
2285   if ( !ok )
2286   {
2287     std::string msg = "Not an integer value:'" + str + "'";
2288     throw std::invalid_argument(msg);
2289   }
2290   return val;
2291 }
2292