Salome HOME
8c0f78d90e7bdc68d7260a902dd61a14b7b4dade
[plugins/ghs3dprlplugin.git] / src / GHS3DPRLPlugin / GHS3DPRLPlugin_GHS3DPRL.cxx
1 // Copyright (C) 2007-2021  CEA/DEN, EDF R&D
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   : GHS3DPRLPlugin_GHS3DPRL.cxx
22 // Author : Christian VAN WAMBEKE (CEA) (from Hexotic plugin Lioka RAZAFINDRAZAKA)
23 // ---
24 //
25 #include "GHS3DPRLPlugin_GHS3DPRL.hxx"
26 #include "GHS3DPRLPlugin_Hypothesis.hxx"
27 #include "MG_TetraHPC_API.hxx"
28
29 #include <SMESHDS_Mesh.hxx>
30 #include <SMESH_Gen.hxx>
31 #include <SMESH_TypeDefs.hxx>
32 #include <SMESH_subMesh.hxx>
33 #include <SMESH_MesherHelper.hxx>
34 #include <SMESH_File.hxx>
35
36 #include "utilities.h"
37
38 #include <list>
39
40 #include <BRepGProp.hxx>
41 #include <GProp_GProps.hxx>
42 #include <OSD_File.hxx>
43 #include <Standard_ProgramError.hxx>
44 #include <TCollection_AsciiString.hxx>
45 #include <TopExp_Explorer.hxx>
46 #include <TopTools_MapOfShape.hxx>
47 #include <TopoDS.hxx>
48 #include <TopoDS_Edge.hxx>
49 #include <TopoDS_Face.hxx>
50
51 #define GMFVERSION GmfDouble
52 #define GMFDIMENSION 3
53
54 using namespace std;
55
56 static void removeFile( const TCollection_AsciiString& fileName )
57 {
58   try {
59     OSD_File( fileName ).Remove();
60   }
61   catch ( Standard_ProgramError& ) {
62     MESSAGE("Can't remove file: " << fileName.ToCString() << " ; file does not exist or permission denied");
63   }
64 }
65
66 //=============================================================================
67 GHS3DPRLPlugin_GHS3DPRL::GHS3DPRLPlugin_GHS3DPRL(int hypId, SMESH_Gen* gen)
68   : SMESH_3D_Algo(hypId, gen)
69 {
70   MESSAGE("GHS3DPRLPlugin_GHS3DPRL::GHS3DPRLPlugin_GHS3DPRL");
71   _name = "MG-Tetra Parallel";
72   _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type
73   _onlyUnaryInput = false; // Compute() will be called on a compound of solids
74   _countSubMesh=0;
75   _nodeRefNumber=0;
76   _compatibleHypothesis.push_back(GHS3DPRLPlugin_Hypothesis::GetHypType());
77   _requireShape=false;
78 }
79
80 //=============================================================================
81 GHS3DPRLPlugin_GHS3DPRL::~GHS3DPRLPlugin_GHS3DPRL()
82 {
83   MESSAGE("GHS3DPRLPlugin_GHS3DPRL::~GHS3DPRLPlugin_GHS3DPRL");
84 }
85
86 //=============================================================================
87 bool GHS3DPRLPlugin_GHS3DPRL::CheckHypothesis
88                          (SMESH_Mesh& aMesh,
89                           const TopoDS_Shape& aShape,
90                           SMESH_Hypothesis::Hypothesis_Status& aStatus)
91 {
92   //MESSAGE("GHS3DPRLPlugin_GHS3DPRL::CheckHypothesis");
93   _hypothesis = NULL;
94
95   list<const SMESHDS_Hypothesis*>::const_iterator itl;
96   const SMESHDS_Hypothesis* theHyp;
97
98   const list<const SMESHDS_Hypothesis*>& hyps = GetUsedHypothesis(aMesh, aShape);
99   int nbHyp = hyps.size();
100   if (!nbHyp)
101   {
102     aStatus = SMESH_Hypothesis::HYP_MISSING;
103     return false;  // can't work with no hypothesis
104   }
105
106   itl = hyps.begin();
107   theHyp = (*itl); // use only the first hypothesis
108
109   string hypName = theHyp->GetName();
110   if (hypName == GHS3DPRLPlugin_Hypothesis::GetHypType())
111   {
112     _hypothesis = static_cast<const GHS3DPRLPlugin_Hypothesis*> (theHyp);
113     ASSERT(_hypothesis);
114     aStatus = SMESH_Hypothesis::HYP_OK;
115   }
116   else
117     aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
118
119   return aStatus == SMESH_Hypothesis::HYP_OK;
120 }
121
122 //=============================================================================
123 // Pass parameters to GHS3DPRL
124 void GHS3DPRLPlugin_GHS3DPRL::SetParameters(const GHS3DPRLPlugin_Hypothesis* hyp)
125 {
126   if (hyp) {
127     MESSAGE("GHS3DPRLPlugin_GHS3DPRL::SetParameters");
128     _MEDName     = hyp->GetMEDName();  //"DOMAIN\0"
129     _NbPart      = hyp->GetNbPart();
130     _KeepFiles   = hyp->GetKeepFiles();
131     _Background  = hyp->GetBackground();
132     _Multithread = hyp->GetMultithread();
133     _Gradation   = hyp->GetGradation();
134     _MinSize     = hyp->GetMinSize();
135     _MaxSize     = hyp->GetMaxSize();
136     _AdvOptions  = hyp->GetAdvancedOption();
137   }
138 }
139
140 //=======================================================================
141 //before launching salome
142 //SALOME_TMP_DIR (for keep tepal intermediates files) could be set in user's directories
143 static TCollection_AsciiString getTmpDir()
144 {
145   TCollection_AsciiString aTmpDir;
146   char *Tmp_dir = getenv("SALOME_TMP_DIR");
147   if (Tmp_dir == NULL) Tmp_dir = getenv("TMP");
148   if(Tmp_dir != NULL)
149   {
150     aTmpDir = Tmp_dir;
151 #ifdef WIN32
152       if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';
153 #else
154       if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';
155 #endif
156   }
157   else
158   {
159 #ifdef WIN32
160       aTmpDir = TCollection_AsciiString("C:\\");
161 #else
162       aTmpDir = TCollection_AsciiString("/tmp/");
163 #endif
164   }
165   return aTmpDir;
166 }
167
168 //=============================================================================
169 // Write a skin mesh into a GMF file or pass it to MG-TetraHPC API
170 static void exportGMF(MG_TetraHPC_API*    theTetraInput,
171                       const char*         theFile,
172                       const SMESHDS_Mesh* theMeshDS)
173 {
174   int meshID = theTetraInput->GmfOpenMesh( theFile, GmfWrite, GMFVERSION, GMFDIMENSION);
175   
176   // nodes
177   int iN = 0, nbNodes = theMeshDS->NbNodes();
178   theTetraInput->GmfSetKwd( meshID, GmfVertices, nbNodes );
179   std::map< const SMDS_MeshNode*, int, TIDCompare > node2IdMap;
180   SMDS_NodeIteratorPtr nodeIt = theMeshDS->nodesIterator();
181   SMESH_TNodeXYZ n;
182   while ( nodeIt->more() )
183   {
184     n.Set( nodeIt->next() );
185     theTetraInput->GmfSetLin( meshID, GmfVertices, n.X(), n.Y(), n.Z(), n._node->getshapeId() );
186     node2IdMap.insert( node2IdMap.end(), std::make_pair( n._node, ++iN ));
187   }
188
189   // triangles
190   SMDS_ElemIteratorPtr elemIt = theMeshDS->elementGeomIterator( SMDSGeom_TRIANGLE );
191   if ( elemIt->more() )
192   {
193     int nbTria = theMeshDS->GetMeshInfo().NbElements( SMDSGeom_TRIANGLE );
194     theTetraInput->GmfSetKwd(meshID, GmfTriangles, nbTria );
195     for ( int gmfID = 1; elemIt->more(); ++gmfID )
196     {
197       const SMDS_MeshElement* tria = elemIt->next();
198       theTetraInput->GmfSetLin(meshID, GmfTriangles, 
199                               node2IdMap[ tria->GetNode( 0 )],
200                               node2IdMap[ tria->GetNode( 1 )],
201                               node2IdMap[ tria->GetNode( 2 )],
202                               tria->getshapeId() );
203     }
204   }
205   theTetraInput->GmfCloseMesh( meshID );
206 }
207
208 //=============================================================================
209 // Here we are going to use the GHS3DPRL mesher for tetra-hpc (formerly tepal in v3 (2014))
210 bool GHS3DPRLPlugin_GHS3DPRL::Compute(SMESH_Mesh&         theMesh,
211                                       const TopoDS_Shape& /*theShape*/)
212 {
213   SMESH_MesherHelper helper( theMesh );
214   bool ok = Compute( theMesh, &helper );
215   return ok;
216 }
217
218 //=============================================================================
219 // Here we are going to use the GHS3DPRL mesher for tetra-hpc (formerly tepal in v3 (2014))
220 bool GHS3DPRLPlugin_GHS3DPRL::Compute(SMESH_Mesh&         theMesh,
221                                       SMESH_MesherHelper* /*theHelper*/)
222 {
223   bool Ok=false;
224   TCollection_AsciiString pluginerror("MG-TETRA_HPC: ");
225   SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
226   if ( theMesh.NbTriangles() == 0 )
227     return error( COMPERR_BAD_INPUT_MESH, "No triangles in the mesh" );
228
229   if (_hypothesis==NULL){
230     pluginerror += "No existing parameters/hypothesis for MG-TETRA_HPC";
231     cout <<"\n"<<pluginerror<<"\n\n";
232     error(COMPERR_ALGO_FAILED, pluginerror.ToCString() );
233     return false;
234   }
235   SetParameters(_hypothesis);
236   cout << "\n" << _name << " parameters:" << endl;
237   cout << "   generic path/name of MED Files = " << _MEDName << endl;
238   cout << "   number of partitions = " << _NbPart << endl;
239   cout << "   gradation = " << _Gradation << endl;
240   cout << "   min_size = " << _MinSize << endl;
241   cout << "   max_size = " << _MaxSize << endl;
242   cout << "   keep intermediates files (from tetra-hpc) = " << _KeepFiles << endl;
243   cout << "   background (from tetra-hpc) = " << _Background << "\n";
244   cout << "   multithread = " << _Multithread << "\n\n";
245   cout << "   adv. options = '" << _AdvOptions << "'\n\n";
246
247   TCollection_AsciiString
248     tmpDir=getTmpDir(),
249     GHS3DPRL_In,
250     GHS3DPRL_Out,
251     GHS3DPRL_Out_Mesh,
252     GHS3DPRL_Outxml,
253     logFileName,
254     run_GHS3DPRL("tetrahpc2med "),
255     rm("rm -f "),
256     run_nokeep_files,
257     NbPart,
258     Gradation,
259     MinSize,
260     MaxSize,
261     fileskinmed(""),
262     fileskinmesh(""),
263     path,
264     casenamemed;  //_MEDName.c_str());
265   int res = 0;    // 0 is OK 
266
267   casenamemed += (char *)_MEDName.c_str();
268   int n=casenamemed.SearchFromEnd('/');
269   if (n>0) {
270     path=casenamemed.SubString(1,n);
271     casenamemed=casenamemed.SubString(n+1,casenamemed.Length());
272   }
273   else
274     path=tmpDir;
275
276   if (casenamemed.Length()>20){
277     casenamemed=casenamemed.SubString(1,20);
278     cerr<<"MEDName truncated (no more 20 characters) = "<<casenamemed<<endl;
279   }
280
281   map <int,int> aSmdsToGHS3DPRLIdMap;
282   map <int,const SMDS_MeshNode*> aGHS3DPRLIdToNodeMap;
283   _genericName = GHS3DPRLPlugin_Hypothesis::GetFileName(_hypothesis);
284   TCollection_AsciiString aGenericName((char*) _genericName.c_str() );
285   GHS3DPRL_In = aGenericName + ".mesh";
286   GHS3DPRL_Out = path + casenamemed;
287   GHS3DPRL_Out_Mesh = aGenericName + "_out.mesh";
288   GHS3DPRL_Outxml = path + casenamemed + ".xml"; //master file
289   logFileName = aGenericName + ".log"; // MG library output
290   NbPart=_NbPart;
291   Gradation=_Gradation;
292   MinSize=_MinSize;
293   MaxSize=_MaxSize;
294
295   //an example:
296   //tetrahpc2med --casename=/home/whoami/tmp/GHS3DPRL --number=5 --medname=DOMAIN
297   //             --gradation=1.05 --min_size=1e-3 --max_size=1e-2
298   //             --verbose=0 --menu=no --launchtetra=yes;
299
300   run_GHS3DPRL = run_GHS3DPRL +
301     " --casename=" + aGenericName +
302     " --number=" + NbPart +
303     " --medname=" + GHS3DPRL_Out +
304     " --launchtetra=yes" +
305     " --gradation=" + Gradation +
306     " --min_size=" + MinSize +
307     " --max_size=" + MaxSize +
308     " --verbose=3" +
309     " " + _AdvOptions.c_str();
310   if (_Background) run_GHS3DPRL += " --background=yes"; else run_GHS3DPRL += " --background=no";
311   if (_Multithread) run_GHS3DPRL += " --multithread=yes"; else run_GHS3DPRL += " --multithread=no";
312   run_nokeep_files = rm +GHS3DPRL_In + "* " + path + "tetrahpc.log";
313   system( run_nokeep_files.ToCString() ); //clean files
314   run_nokeep_files = rm + GHS3DPRL_In + "* ";
315
316   removeFile( GHS3DPRL_Outxml ); //only the master xml file
317
318   MG_TetraHPC_API mgTetraHPC( _computeCanceled, _progress );
319   bool useLib = ( mgTetraHPC.IsLibrary() && !_Background && _Multithread );
320   if ( !useLib )
321     mgTetraHPC.SetUseExecutable();
322
323   exportGMF( &mgTetraHPC, GHS3DPRL_In.ToCString(), meshDS );
324
325   if ( true /*useLib*/ )
326   {
327     TCollection_AsciiString cmd = TCollection_AsciiString();
328     if (_Multithread)
329       cmd += "mg-tetra_hpc.exe";
330     else
331       cmd = cmd + "mpirun --n " + NbPart + " mg-tetra_hpc_mpi.exe";
332     cmd = cmd + " --in=" + GHS3DPRL_In;
333     if (_Multithread)
334       cmd = cmd +" --max_number_of_threads=" + NbPart;
335     cmd = cmd + " --gradation=" + Gradation;
336     cmd = cmd + " --min_size=" + MinSize;
337     cmd = cmd + " --max_size=" + MaxSize;
338     cmd = cmd + " --verbose=3";
339     cmd = cmd + " --out=" + GHS3DPRL_Out_Mesh;
340     cmd = cmd + " " + _AdvOptions.c_str();
341     cmd = cmd + " 1>" + logFileName;
342
343     cout << endl
344          << "  Run mg-tetra_hpc as library. Creating a mesh file " << GHS3DPRL_Out_Mesh << endl
345          << "  Creating a log file : " << logFileName << endl << endl;
346     mgTetraHPC.SetLogFile( logFileName.ToCString() );
347
348     std::string log;
349     Ok = mgTetraHPC.Compute( cmd.ToCString(), log );
350
351     if (!Ok)
352     {
353       std::cout << "Error: " << std::endl;
354       std::cout << log << std::endl;
355       // try to guess an error from the output log
356       std::string log2 = mgTetraHPC.GetLog();
357       if ( log2.find("Dlim"   ) != std::string::npos ||
358           log2.find("icense") != std::string::npos )
359         return error("License problem");
360       std::cout << log2 << std::endl;
361       if ( log2.find("You are using an empty MPI stubs library") != std::string::npos )
362       {
363         std:string msg = "You are using an empty MPI stubs library. Please build it first to be able to use mg-tetra_hpc_mpi.exe.\n";
364         msg += "./salome context\n";
365         msg += "cd $MESHGEMSHOME/stubs\n";
366         msg += "mpicc meshgems_mpi.c -DMESHGEMS_LINUX_BUILD -I../include -shared -fPIC -o $MESHGEMSHOME/lib/Linux_64/libmeshgems_mpi.so";
367         return error(msg);
368       }
369       return error(log);
370     }
371
372     // set --launchtetra=no
373     int yesPos = run_GHS3DPRL.Search("launchtetra") + sizeof("launchtetra");
374     run_GHS3DPRL.SetValue( yesPos+0, 'n' );
375     run_GHS3DPRL.SetValue( yesPos+1, 'o' );
376     run_GHS3DPRL.SetValue( yesPos+2, ' ' );
377   }
378   else
379   {
380     cout<<"  Write input file for mg-tetra_hpc "<<fileskinmesh<<"...";
381     cout<<" ...done\n";
382   }
383
384   if (!_Multithread)
385   {
386     fileskinmed=path + casenamemed + "_skin.med";
387     cout<<"  Write file "<<fileskinmed<<"...";
388     theMesh.ExportMED(fileskinmed.ToCString(),"SKIN_INITIAL",true);
389     cout<<" ...done\n\n";
390   }
391
392   // convert .mesh (one or several) to med file(s) with xml master file if mpi
393   cout<<"Mesh conversion command :\n  "<<run_GHS3DPRL.ToCString()<<endl;
394   //sometimes it is better to wait flushing files on slow filesystem...
395   //   system( "sleep 3" );
396   //launch tetrahpc2med which launch mg-tetra_hpc.py which launch mg-tetra_hpc(_mpi?).exe
397   res = system( run_GHS3DPRL.ToCString() );
398   if (res > 0)
399   {
400     pluginerror = pluginerror + "PROBLEM tetrahpc2med command";
401     cout<<pluginerror<<endl;
402     error(COMPERR_ALGO_FAILED, pluginerror.ToCString());
403     return false; //but it is not a problem but if true my message is overwritten
404   }
405   //system( "sleep 3" );
406
407   if (_Background) {
408     pluginerror = pluginerror + "backgrounding... plugin is not waiting for output files "+ path +casenamemed + "_*.med";
409     cout<<pluginerror<<endl;
410     error(COMPERR_NO_MESH_ON_SHAPE, pluginerror.ToCString());
411     return false; //but it is not a problem but if true my message is overwritten
412     //return true; //but it is not a problem,
413   }
414
415   if (_Multithread)
416   {
417     // check the med file has been created (only one med file, since multithread)
418     TCollection_AsciiString resuMedFile = TCollection_AsciiString(path) + casenamemed + "_1.med";
419     SMESH_File file( resuMedFile.ToCString() );
420     if (file.exists() && file.size() > 0)
421     {
422       Ok = true;
423       pluginerror = pluginerror + "MG-tetra_hpc mesh not loaded in memory, is stored in file "+ resuMedFile;
424       cout<<pluginerror<<endl;
425       error(COMPERR_WARNING, pluginerror.ToCString() );
426       if (!_KeepFiles) system( run_nokeep_files.ToCString() );
427     }
428   }
429   else
430   {
431     // read a result, GHS3DPRL_Outxml is the name of master file (previous xml format)
432     FILE * aResultFile = fopen( GHS3DPRL_Outxml.ToCString(), "r" );
433     if (aResultFile){
434       Ok = true;
435       fclose(aResultFile);
436       cout<<"MG-TETRA_HPC OK output master file "<<casenamemed<<".xml exist !\n\n";
437       pluginerror = pluginerror + "MG-tetra_hpc meshes not loaded in memory, are stored in files "+ path + casenamemed + "_*.med";
438       cout<<pluginerror<<endl;
439       error(COMPERR_WARNING, pluginerror.ToCString() );
440       if (!_KeepFiles) system( run_nokeep_files.ToCString() );
441     }
442     else{
443       Ok = false; //it is a problem AND my message is NOT overwritten
444       pluginerror = pluginerror + "output master file " + casenamemed + ".xml do not exist";
445       cout<<pluginerror<<endl;
446       error(COMPERR_ALGO_FAILED, pluginerror.ToCString() );
447       cout<<"MG-TETRA_HPC KO output files "<<GHS3DPRL_Out<<" do not exist ! see intermediate files kept:\n";
448       TCollection_AsciiString run_list_files("ls -alt ");
449       run_list_files +=  GHS3DPRL_Out + "* " + GHS3DPRL_In + "* " + logFileName;
450       system( run_list_files.ToCString() );
451       cout<<endl;
452     }
453   }
454
455
456   return Ok;
457 }
458
459
460
461 //=============================================================================
462 /*!
463  *
464  */
465 //=============================================================================
466 bool GHS3DPRLPlugin_GHS3DPRL::Evaluate(SMESH_Mesh& aMesh,
467                                        const TopoDS_Shape& aShape,
468                                        MapShapeNbElems& aResMap)
469 {
470   smIdType nbtri = 0, nbqua = 0;
471   double fullArea = 0.0;
472   for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next()) {
473     TopoDS_Face F = TopoDS::Face( exp.Current() );
474     SMESH_subMesh *sm = aMesh.GetSubMesh(F);
475     MapShapeNbElemsItr anIt = aResMap.find(sm);
476     if( anIt==aResMap.end() ) {
477       SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
478       smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,
479                                             "Submesh can not be evaluated",this));
480       return false;
481     }
482     std::vector<smIdType> aVec = (*anIt).second;
483     nbtri += std::max(aVec[SMDSEntity_Triangle],aVec[SMDSEntity_Quad_Triangle]);
484     nbqua += std::max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]);
485     GProp_GProps G;
486     BRepGProp::SurfaceProperties(F,G);
487     double anArea = G.Mass();
488     fullArea += anArea;
489   }
490
491   // collect info from edges
492   smIdType nb0d_e = 0, nb1d_e = 0;
493   bool IsQuadratic = false;
494   bool IsFirst = true;
495   TopTools_MapOfShape tmpMap;
496   for (TopExp_Explorer exp(aShape, TopAbs_EDGE); exp.More(); exp.Next()) {
497     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
498     if( tmpMap.Contains(E) )
499       continue;
500     tmpMap.Add(E);
501     SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current());
502     MapShapeNbElemsItr anIt = aResMap.find(aSubMesh);
503     std::vector<smIdType> aVec = (*anIt).second;
504     nb0d_e += aVec[SMDSEntity_Node];
505     nb1d_e += std::max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]);
506     if(IsFirst) {
507       IsQuadratic = (aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge]);
508       IsFirst = false;
509     }
510   }
511   tmpMap.Clear();
512
513   double ELen = sqrt(2.* ( fullArea/(nbtri+nbqua*2) ) / sqrt(3.0) );
514
515   GProp_GProps G;
516   BRepGProp::VolumeProperties(aShape,G);
517   double aVolume = G.Mass();
518   double tetrVol = 0.1179*ELen*ELen*ELen;
519   double CoeffQuality = 0.9;
520   smIdType nbVols = (smIdType)aVolume/tetrVol/CoeffQuality;
521   smIdType nb1d_f = (nbtri*3 + nbqua*4 - nb1d_e) / 2;
522   smIdType nb1d_in = (smIdType) ( nbVols*6 - nb1d_e - nb1d_f ) / 5;
523   std::vector<smIdType> aVec(SMDSEntity_Last);
524   for(smIdType i=0; i<SMDSEntity_Last; i++) aVec[i]=0;
525   if( IsQuadratic ) {
526     aVec[SMDSEntity_Node] = nb1d_in/6 + 1 + nb1d_in;
527     aVec[SMDSEntity_Quad_Tetra] = nbVols - nbqua*2;
528     aVec[SMDSEntity_Quad_Pyramid] = nbqua;
529   }
530   else {
531     aVec[SMDSEntity_Node] = nb1d_in/6 + 1;
532     aVec[SMDSEntity_Tetra] = nbVols - nbqua*2;
533     aVec[SMDSEntity_Pyramid] = nbqua;
534   }
535   SMESH_subMesh *sm = aMesh.GetSubMesh(aShape);
536   aResMap.insert(std::make_pair(sm,aVec));
537
538   return true;
539 }