Salome HOME
52db6e97ed7a43fb4124ec0844d6bc99d7a2ce57
[tools/medcoupling.git] / src / MEDPartitioner / MEDPARTITIONER_Utils.cxx
1 // Copyright (C) 2007-2020  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 #include "MEDPARTITIONER_Utils.hxx"
21
22 #include "MEDLoader.hxx"
23 #include "MEDLoaderBase.hxx"
24 #include "MEDFileUtilities.hxx"
25 #include "CellModel.hxx"
26 #include "MEDCouplingUMesh.hxx"
27 #include "MEDCouplingFieldDouble.hxx"
28 #include "InterpKernelException.hxx"
29 #include "MCAuto.hxx"
30 #include "InterpKernelAutoPtr.hxx"
31
32 #include <fstream>
33 #include <iostream>
34 #include <iomanip>
35 #include <sstream>
36 #include <string>
37 #include <cstring>
38
39 using namespace MEDPARTITIONER;
40
41 int MEDPARTITIONER::MyGlobals::_Verbose=0;
42 int MEDPARTITIONER::MyGlobals::_Is0verbose=0;
43 int MEDPARTITIONER::MyGlobals::_Rank=-1;
44 int MEDPARTITIONER::MyGlobals::_World_Size=-1;
45 int MEDPARTITIONER::MyGlobals::_Randomize=0;
46 int MEDPARTITIONER::MyGlobals::_Atomize=0;
47 int MEDPARTITIONER::MyGlobals::_Create_Boundary_Faces=0;
48 int MEDPARTITIONER::MyGlobals::_Create_Joints=0;
49 std::vector<std::string> MEDPARTITIONER::MyGlobals::_File_Names;
50 std::vector<std::string> MEDPARTITIONER::MyGlobals::_Mesh_Names;
51 std::vector<std::string> MEDPARTITIONER::MyGlobals::_Field_Descriptions;
52 std::vector<std::string> MEDPARTITIONER::MyGlobals::_General_Informations;
53
54 std::string MEDPARTITIONER::Trim(const std::string& s,const std::string& drop)
55 {
56   std::string r(s);
57   r.erase(r.find_last_not_of(drop)+1);
58   return r.erase(0,r.find_first_not_of(drop));
59 }
60
61 std::string MEDPARTITIONER::IntToStr(const int i)
62 {
63   std::ostringstream oss;
64   oss << i;
65   return oss.str();
66 }
67
68 std::string MEDPARTITIONER::DoubleToStr(const double i)
69 {
70   std::ostringstream oss;
71   oss << i;
72   return oss.str();
73 }
74
75 int MEDPARTITIONER::StrToInt(const std::string& s)
76 {
77   int res;
78   std::istringstream iss(s);
79   iss >> res;
80   return res;
81 }
82
83 double MEDPARTITIONER::StrToDouble(const std::string& s)
84 {
85   double res;
86   std::istringstream iss(s);
87   iss >> res;
88   return res;
89 }
90
91 bool MEDPARTITIONER::TestArg(const char *arg, const char *argExpected, std::string& argValue)
92 {
93   argValue="";
94   std::size_t i;
95   for (i=0; i<strlen(arg); i++)
96     {
97       if (arg[i]=='=')
98         break;
99       if (arg[i]!=argExpected[i])
100         return false;
101     }
102   for (std::size_t j=i+1; j<strlen(arg); j++)
103     argValue+=arg[j];
104   return true;
105 }
106
107 std::vector<int> MEDPARTITIONER::CreateRandomSize(const int size)
108 {
109   std::vector<int> res(size);
110   for (int i=0; i<size; i++)
111     res[i]=i;
112   //cvw TODO or not? srand( (unsigned)time( NULL ) );
113   srand( MyGlobals::_Randomize );
114   for (int i=0; i<size; i++)
115     {
116       int ii=rand()%size;
117       int tmp=res[ii];
118       res[ii]=res[i];
119       res[i]=tmp;
120     }
121   return res;
122 }
123
124 /*!
125  * randomize a xadj and adjncy, renumbering vertices belong rand. Works only on one processor!!!!
126  */
127 void MEDPARTITIONER::RandomizeAdj(int* xadj, int* adjncy, std::vector<int>& ran, std::vector<int>& vx, std::vector<int>& va)
128 {
129   if (MyGlobals::_World_Size>1)
130     {
131       std::cerr << "MEDPARTITIONER::RandomizeAdj only works on one proc!" << std::endl;
132       return;
133     }
134   std::size_t size=ran.size();
135   std::vector<int> invran(size);
136   for (unsigned int i=0; i<size; i++)
137     invran[ran[i]]=i;
138   vx.resize(size+1);
139   int lga=xadj[size];
140   va.resize(lga);
141   int jj=0;
142   vx[0]=0;
143   for (std::size_t i=0; i<size; i++)
144     {
145       int ir=ran[i];
146       int ii=xadj[ir];
147       int lgj=xadj[ir+1]-ii;
148       for (int j=0; j<lgj; j++)
149         {
150           va[jj]=invran[adjncy[ii]];
151           jj=jj+1;
152           ii=ii+1;
153         }
154       vx[i+1]=jj;
155     }
156 }
157
158 void MEDPARTITIONER::TestRandomize()
159 {
160   //int xadj[6]={0,2,5,9,12,13}; //for first debug only
161   //int adjncy[13]={1,4,0,2,4,1,3,4,2,4,4,3,4};
162   int xadj[6]={0,2,5,9,12,13};
163   int adjncy[13]={0,0,1,1,1,2,2,2,2,3,3,3,4};
164   int size=5;
165   std::vector<int> r=CreateRandomSize(size);
166   std::vector<int> vx,va;
167   RandomizeAdj(&xadj[0],&adjncy[0],r,vx,va);
168 }
169
170 std::string MEDPARTITIONER::ReprVectorOfString(const std::vector<std::string>& vec)
171 {
172   if (vec.size()==0)
173     return std::string(" NONE\n");
174   std::ostringstream oss;
175   for (std::vector<std::string>::const_iterator i=vec.begin(); i!=vec.end(); ++i) 
176     oss << " -> '" << *i << "'" << std::endl;
177   return oss.str();
178 }
179
180 std::string MEDPARTITIONER::ReprVectorOfString(const std::vector<std::string>& vec, const std::string separator)
181 {
182   if (vec.size()==0)
183     return std::string(" NONE\n");
184   std::ostringstream oss;
185   for (std::vector<std::string>::const_iterator i=vec.begin(); i!=vec.end(); ++i) 
186     oss << separator << *i;
187   return oss.str();
188 }
189
190 std::string MEDPARTITIONER::ReprMapOfStringInt(const std::map<std::string,mcIdType>& mymap)
191 {
192   if (mymap.size()==0)
193     return std::string(" NONE\n");
194   std::ostringstream oss;
195   for (std::map<std::string,mcIdType>::const_iterator i=mymap.begin(); i!=mymap.end(); ++i) 
196     oss << " -> [" << (*i).first << "]=" << (*i).second << std::endl;
197   return oss.str();
198 }
199
200 std::string MEDPARTITIONER::ReprMapOfStringVectorOfString(const std::map< std::string,std::vector<std::string> >& mymap)
201 {
202   if (mymap.size()==0)
203     return std::string(" NONE\n");
204   std::ostringstream oss;
205   for (std::map< std::string,std::vector<std::string> >::const_iterator i=mymap.begin(); i!=mymap.end(); ++i) 
206     oss << " -> [" << (*i).first << "]=" << std::endl << ReprVectorOfString((*i).second) << std::endl;
207   return oss.str();
208 }
209
210 std::string MEDPARTITIONER::ReprFieldDescriptions(const std::vector<std::string>& vec, const std::string separator)
211 {
212   if (vec.size()==0)
213     return std::string(" NONE\n");
214   std::ostringstream oss;
215   for (std::vector<std::string>::const_iterator i=vec.begin(); i!=vec.end(); ++i)
216     {
217       oss << " ->"; 
218       oss << ReprVectorOfString(DeserializeToVectorOfString(*i), separator) << std::endl;
219     }
220   return oss.str();
221 }
222
223 /*!
224  * a string "hello" gives a string "    5/hello/"
225  * serialized_FromVectorOfString_string+SerializeFromString("toto") is
226  * equivalent to vector<string>.push_back("toto") on serialized_FromVectorOfString_string
227  */
228 std::string MEDPARTITIONER::SerializeFromString(const std::string& s)
229 {
230   std::ostringstream oss;
231   oss << std::setw(5) << s.size() << "/" << s << "/";
232   return oss.str();
233 }
234
235 /*!
236  * a vector of string gives a string
237  */
238 std::string MEDPARTITIONER::SerializeFromVectorOfString(const std::vector<std::string>& vec)
239 {
240   std::ostringstream oss;
241   for (std::vector<std::string>::const_iterator i=vec.begin(); i!=vec.end(); ++i)
242     oss<< std::setw(5) << (*i).size() << "/" << *i << "/";
243   return oss.str();
244 }
245
246 /*!
247  * a string gives a vector of string
248  */
249 std::vector<std::string> MEDPARTITIONER::DeserializeToVectorOfString(const std::string& str)
250 {
251   std::vector<std::string> res;
252   std::size_t pos=0;
253   std::size_t posmax=str.size();
254   if (posmax==0)
255     return res;  //empty vector
256   std::size_t length;
257   while (pos < posmax-6)  //setw(5)+" "
258     {
259       std::istringstream iss(str.substr(pos,5));
260       iss >> length;
261       if ((str[pos+5]!='/') || (str[pos+6+length]!='/'))
262         {
263           std::cerr << "Error on string '" << str << "'" << std::endl;;
264           throw INTERP_KERNEL::Exception("Error on string");
265         }
266       res.push_back(str.substr(pos+6,length));
267       pos=pos+6+length+1;
268     }
269   return res;
270 }
271
272 std::string MEDPARTITIONER::EraseTagSerialized(const std::string& fromStr, const std::string& tag)
273 {
274   std::vector<std::string> vec=DeserializeToVectorOfString(fromStr);
275   std::vector<std::string> res;
276   for (std::size_t i=0; i<vec.size(); i++)
277     {
278       if (vec[i].find(tag)==std::string::npos)
279         res.push_back(vec[i]);
280     }
281   return MEDPARTITIONER::SerializeFromVectorOfString(res);
282 }
283
284 /*!
285  * elements first and second of map give one elements in result vector of string
286  * converting formatted the int second as firsts characters ending at first slash
287  */
288 std::vector<std::string> MEDPARTITIONER::VectorizeFromMapOfStringInt(const std::map<std::string,mcIdType>& mymap)
289 {
290   std::vector<std::string> res;
291   for (std::map<std::string,mcIdType>::const_iterator i=mymap.begin(); i!=mymap.end(); ++i)
292     {
293       std::ostringstream oss;
294       oss << (*i).second << "/" << (*i).first;
295       res.push_back(oss.str());
296     }
297   return res;
298 }
299
300 /*
301  * if existing identicals (first,second) in vector no problem, else Exception
302  */
303 std::map<std::string,mcIdType> MEDPARTITIONER::DevectorizeToMapOfStringInt(const std::vector<std::string>& vec)
304 {
305   std::map<std::string,mcIdType> res;
306   for (std::vector<std::string>::const_iterator i=vec.begin(); i!=vec.end(); ++i)
307     {
308       std::size_t pos=0;
309       std::size_t posmax=(*i).size();
310       std::size_t found=(*i).find('/'); //first slash
311       if ((found==std::string::npos) || (found<1))
312         throw INTERP_KERNEL::Exception("Error aIntNumber/anyString is expected");
313       mcIdType second;
314       std::istringstream iss((*i).substr(pos,found));
315       iss >> second;
316       std::string first=(*i).substr(pos+found+1,posmax-found);
317       std::map<std::string,mcIdType>::iterator it=res.find(first);
318       if (it!=res.end())
319         if ((*it).second!=second)
320           throw INTERP_KERNEL::Exception("Error not the same map value");
321       res[first]=second;
322     }
323   return res;
324 }
325
326 /*!
327  * elements first and second of map give one elements in result vector of string
328  * adding key map and length of second vector as first string in each serialized vector
329  * one serialized vector per key map
330  */
331 std::vector<std::string> MEDPARTITIONER::VectorizeFromMapOfStringVectorOfString(const std::map< std::string,std::vector<std::string> >& mymap)
332 {
333   std::vector<std::string> res;
334   for (std::map< std::string,std::vector<std::string> >::const_iterator i=mymap.begin(); i!=mymap.end(); ++i)
335     {
336       std::vector<std::string> vs=(*i).second;  //a vector of string;
337       std::ostringstream oss;
338       oss << "Keymap/" << (*i).first << "/" << (*i).second.size();
339       vs.insert(vs.begin(), oss.str());
340       res.push_back(SerializeFromVectorOfString(vs));
341     }
342   return res;
343 }
344
345 /*!
346  * if existing identicals keymap in vector no problem
347  * duplicates in second vector
348  */
349 std::map< std::string,std::vector<std::string> > MEDPARTITIONER::DevectorizeToMapOfStringVectorOfString(const std::vector<std::string>& vec)
350 {
351   std::map< std::string,std::vector<std::string> > res;
352   for (std::vector<std::string>::const_iterator i=vec.begin(); i!=vec.end(); ++i)
353     {
354       std::vector<std::string> vs=DeserializeToVectorOfString(*i);
355     
356       std::string enTete=vs[0];
357       std::size_t posmax=enTete.size();
358       std::size_t foundKey=enTete.find("Keymap/");
359       std::size_t foundSizeVector=enTete.find_last_of('/');
360       if ((foundKey==std::string::npos) || (foundKey!=0) || ((foundKey+7)>=foundSizeVector))
361         throw INTERP_KERNEL::Exception("Error Keymap/anyString/aIntNumber is expected");
362       int sizeVector;
363       std::istringstream iss(enTete.substr(foundSizeVector+1,posmax-foundSizeVector));
364       iss >> sizeVector;
365       std::string keymap=enTete.substr(foundKey+7,foundSizeVector-foundKey-7);
366       for (int ii=1; ii<=sizeVector; ii++)
367         res[keymap].push_back(vs[ii]); //add unconditionally,so merge duplicates in second vector
368     }
369   return res;
370 }
371
372 /*!
373  * shit for unique and unique_copy for the duplicate CONSECUTIVE elements
374  * I do not want to sort
375  */
376 std::vector<std::string> MEDPARTITIONER::SelectTagsInVectorOfString(const std::vector<std::string>& vec, const std::string tag)
377 {
378   std::vector<std::string> res;
379   if (vec.size()==0)
380     return res;
381   for (std::vector<std::string>::const_iterator i=vec.begin(); i!=vec.end(); ++i)
382     {
383       if ((*i).find(tag)!=std::string::npos) res.push_back(*i);
384     }
385   return res;
386 }
387
388 /*!
389  * 
390  */
391 std::vector<std::string> MEDPARTITIONER::DeleteDuplicatesInVectorOfString(const std::vector<std::string>& vec)
392 {
393   std::vector<std::string> res;
394   if (vec.size()==0) return res;
395   //shit for unique and unique_copy for the duplicate CONSECUTIVE elements
396   //I do not want to sort
397   for (std::vector<std::string>::const_iterator i=vec.begin(); i!=vec.end(); ++i)
398     {
399       bool found=false;
400       for (std::vector<std::string>::const_iterator j=res.begin(); j!=res.end(); ++j)
401         {
402           if ((*i).compare(*j)==0)
403             {
404               found=true;
405               break;
406             }
407         }
408       if (!found) res.push_back(*i);
409     }
410   return res;
411 }
412
413 std::map< std::string,std::vector<std::string> > MEDPARTITIONER::DeleteDuplicatesInMapOfStringVectorOfString(const std::map< std::string,std::vector<std::string> >& mymap)
414 {
415   std::map< std::string,std::vector<std::string> > res;
416   for (std::map< std::string,std::vector<std::string> >::const_iterator i=mymap.begin(); i!=mymap.end(); ++i)
417     res[(*i).first]=DeleteDuplicatesInVectorOfString((*i).second);
418   return res;
419 }
420
421 //void MEDPARTITIONER::sendRecvVectorOfString(const std::vector<string>& vec, const int source, const int target)
422 //TODO
423 std::string MEDPARTITIONER::Cle1ToStr(const std::string& s, const int inew)
424 {
425   std::ostringstream oss;
426   oss << s << " " << inew;
427   return oss.str();
428 }
429
430 void MEDPARTITIONER::Cle1ToData(const std::string& key, std::string& s, int& inew)
431 {
432   std::size_t posmax=key.size();
433   std::size_t found=key.find(' ');
434   if ((found==std::string::npos) || (found<1))
435     throw INTERP_KERNEL::Exception("Error 'aStringWithoutWhitespace aInt' is expected");
436   s=key.substr(0,found);
437   std::istringstream iss(key.substr(found,posmax-found));
438   iss >> inew;
439 }
440
441 std::string MEDPARTITIONER::Cle2ToStr(const std::string& s, const int inew, const int iold)
442 {
443   std::ostringstream oss;
444   oss << s << " " << inew << " " << iold;
445   return oss.str();
446 }
447
448 void MEDPARTITIONER::Cle2ToData(const std::string& key, std::string& s, int& inew, int& iold)
449 {
450   std::size_t posmax=key.size();
451   std::size_t found=key.find(' ');
452   if ((found==std::string::npos) || (found<1))
453     throw INTERP_KERNEL::Exception("Error 'aStringWithoutWhitespace aInt aInt' is expected");
454   s=key.substr(0,found);
455   std::istringstream iss(key.substr(found,posmax-found));
456   iss >> inew >> iold;
457 }
458
459 std::string MEDPARTITIONER::ExtractFromDescription(const std::string& description,const std::string& tag)
460 {
461   std::size_t found=description.find(tag);
462   if ((found==std::string::npos) || (found<1))
463     {
464       std::cerr << "ERROR : not found '" << tag << "' in '"<< description << "'\n";
465       throw INTERP_KERNEL::Exception("Error ExtractFromDescription");
466     }
467   std::size_t beg=found;
468   std::size_t end=beg;
469   if (description[found-1]!='/')
470     {
471       //find without '/'... and pray looking for first whitespace
472       //something like 'idomain=0 fileName=tmp.med meshName=...'
473       end=description.size();
474       beg+=tag.length();
475       std::string res=description.substr(beg,end-beg);
476       found=res.find(' ');
477       if (found==std::string::npos)
478         found=res.length();
479       res=res.substr(0,found);
480       return res;
481     }
482   std::size_t lg=StrToInt(description.substr(found-6,found));
483   beg+=tag.length();
484   return description.substr(beg,lg-tag.length());
485 }
486
487 void MEDPARTITIONER::FieldDescriptionToData(const std::string& description, 
488                                             int& idomain, std::string& fileName, std::string& meshName, std::string& fieldName, int& typeField, int& DT, int& IT)
489 {
490   idomain=StrToInt(ExtractFromDescription(description,"idomain="));
491   fileName=ExtractFromDescription(description,"fileName=");
492   meshName=ExtractFromDescription(description,"meshName=");
493   fieldName=ExtractFromDescription(description,"fieldName=");
494   typeField=StrToInt(ExtractFromDescription(description,"typeField="));
495   DT=StrToInt(ExtractFromDescription(description,"DT="));
496   IT=StrToInt(ExtractFromDescription(description,"IT="));
497 }
498
499 void MEDPARTITIONER::FieldShortDescriptionToData(const std::string& description, 
500                                                  std::string& fieldName, int& typeField, int& entity, int& DT, int& IT)
501 {
502   fieldName=ExtractFromDescription(description,"fieldName=");
503   typeField=StrToInt(ExtractFromDescription(description,"typeField="));
504   entity=StrToInt(ExtractFromDescription(description,"entity="));
505   DT=StrToInt(ExtractFromDescription(description,"DT="));
506   IT=StrToInt(ExtractFromDescription(description,"IT="));
507 }
508
509 MEDCoupling::DataArrayIdType *MEDPARTITIONER::CreateDataArrayIntFromVector(const std::vector<mcIdType>& v)
510 {
511   MEDCoupling::DataArrayIdType* p=MEDCoupling::DataArrayIdType::New();
512   p->alloc(v.size(),1);
513   std::copy(v.begin(),v.end(),p->getPointer());
514   return p;
515 }
516
517 MEDCoupling::DataArrayIdType *MEDPARTITIONER::CreateDataArrayIntFromVector(const std::vector<mcIdType>& v,const int nbComponents)
518 {
519   MEDCoupling::DataArrayIdType* p=MEDCoupling::DataArrayIdType::New();
520   if (v.size()%nbComponents!=0)
521     throw INTERP_KERNEL::Exception("Problem size modulo nbComponents != 0");
522   p->alloc(v.size()/nbComponents,nbComponents);
523   std::copy(v.begin(),v.end(),p->getPointer());
524   return p;
525 }
526
527 MEDCoupling::DataArrayDouble* MEDPARTITIONER::CreateDataArrayDoubleFromVector(const std::vector<double>& v)
528 {
529   MEDCoupling::DataArrayDouble* p=MEDCoupling::DataArrayDouble::New();
530   p->alloc(v.size(),1);
531   std::copy(v.begin(),v.end(),p->getPointer());
532   return p;
533 }
534
535 /*!
536  */
537 std::vector<std::string> MEDPARTITIONER::BrowseFieldDouble(const MEDCoupling::MEDCouplingFieldDouble* fd)
538 {
539   std::vector<std::string> res;
540   if (fd->getArray())
541     {
542       std::size_t nb=fd->getArray()->getNumberOfComponents();
543       res.push_back("nbComponents="); res.back()+=IntToStr((int)nb);
544       for (unsigned int i=0; i<nb; i++)
545         {
546           res.push_back("componentInfo");
547           res.back()+=IntToStr(i)+"="+fd->getArray()->getInfoOnComponent(i);
548         }
549     }
550   else
551     {
552       res.push_back("nbComponents=0");  //unknown
553     }
554   return res;
555 }
556
557 /*!
558  * quick almost human readable information on all fields in a .med file
559  */
560 std::vector<std::string> MEDPARTITIONER::BrowseAllFields(const std::string& myfile)
561 {
562   std::vector<std::string> res;
563   std::vector<std::string> meshNames=MEDCoupling::GetMeshNames(myfile);
564   
565   for (std::size_t i=0; i<meshNames.size(); i++)
566     {
567       std::vector<std::string> fieldNames=
568         MEDCoupling::GetAllFieldNamesOnMesh(myfile,meshNames[i]);
569       for (std::size_t j = 0; j < fieldNames.size(); j++)
570         {
571           std::vector< MEDCoupling::TypeOfField > typeFields=
572             MEDCoupling::GetTypesOfField(myfile, meshNames[i], fieldNames[j]);
573           for (std::size_t k = 0; k < typeFields.size(); k++)
574             {
575               std::vector< std::pair< int, int > > its=
576                 GetFieldIterations(typeFields[k], myfile, meshNames[i], fieldNames[j]);
577               if (MyGlobals::_Is0verbose>100)
578                 std::cout<< "fieldName " << fieldNames[j] << " typeField " << typeFields[k] << " its.size() " << its.size() << std::endl;
579               for (std::size_t m = 0; m < its.size(); m++)
580                 {
581                   std::vector<std::string> resi;
582                   resi.push_back("fileName="); resi.back()+=myfile;
583                   resi.push_back("meshName="); resi.back()+=meshNames[i];
584                   resi.push_back("fieldName="); resi.back()+=fieldNames[j];
585                   resi.push_back("typeField="); resi.back()+=IntToStr((int)typeFields[k]);
586                   resi.push_back("DT="); resi.back()+=IntToStr((int)its[m].first);
587                   resi.push_back("IT="); resi.back()+=IntToStr((int)its[m].second);
588                   res.push_back(SerializeFromVectorOfString(resi));
589                 }
590             }
591         }
592     }
593   return res;
594 }
595
596 std::vector<std::string> MEDPARTITIONER::GetInfosOfField(const char *fileName, const char *meshName, const int idomain)
597 {
598   const int lggeom=10;
599   const med_geometry_type GEOMTYPE[lggeom]={ //MED_N_CELL_FIXED_GEO] = { 
600     //MED_POINT1,
601     //MED_SEG2,
602     //MED_SEG3,
603     //MED_SEG4,
604     //MED_TRIA3,
605     //MED_QUAD4,
606     //MED_TRIA6,
607     //MED_TRIA7,
608     //MED_QUAD8,
609     //MED_QUAD9,
610     MED_TETRA4,
611     MED_PYRA5,
612     MED_PENTA6,
613     MED_HEXA8,
614     MED_OCTA12,
615     MED_TETRA10,
616     MED_PYRA13,
617     MED_PENTA15,
618     MED_HEXA20,
619     MED_HEXA27,
620     //MED_POLYGON,
621     //MED_POLYHEDRON 
622   };
623
624   const char * const GEOMTYPENAME[lggeom]={
625     //"MED_POINT1",
626     //"MED_SEG2",
627     //"MED_SEG3",
628     //"MED_SEG4",
629     //"MED_TRIA3",
630     //"MED_QUAD4",
631     //"MED_TRIA6",
632     //"MED_TRIA7",
633     //"MED_QUAD8",
634     //"MED_QUAD9",
635     "MED_TETRA4",
636     "MED_PYRA5",
637     "MED_PENTA6",
638     "MED_HEXA8",
639     "MED_OCTA12",
640     "MED_TETRA10",
641     "MED_PYRA13",
642     "MED_PENTA15",
643     "MED_HEXA20",
644     "MED_HEXA27",
645     //"MED_POLYGONE",
646     //"MED_POLYEDRE",
647   };
648
649
650   const int lgentity=3;
651   const med_entity_type ENTITYTYPE[lgentity]={ //MED_N_ENTITY_TYPES+2]={
652     //MED_UNDEF_ENTITY_TYPE,
653     MED_CELL,
654     //MED_DESCENDING_FACE,
655     //MED_DESCENDING_EDGE,
656     MED_NODE,
657     MED_NODE_ELEMENT,
658     //MED_STRUCT_ELEMENT,
659     //MED_UNDEF_ENTITY_TYPE
660   };
661
662   const char * const ENTITYTYPENAME[lgentity]={ //MED_N_ENTITY_TYPES+2]={
663     //"MED_UNDEF_ENTITY_TYPE",
664     "MED_CELL",
665     //"MED_FACE",
666     //"MED_ARETE",
667     "MED_NODE",
668     "MED_NODE_ELEMENT",
669     //"MED_STRUCT_ELEMENT",
670     //"MED_UNDEF_ENTITY_TYPE"
671   };
672   
673   std::vector<std::string> res;
674   med_idt fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
675   med_int nbFields=MEDnField(fid);
676   if (MyGlobals::_Verbose>20)
677     std::cout << "on filename " << fileName << " nbOfField " << nbFields << std::endl;
678   //
679   med_field_type typcha;
680   med_int numdt=0,numo=0;
681   med_float dt=0.0;
682   char *maa_ass=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
683   char *nomcha=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
684   med_bool localmesh;
685   //
686   for(int i=1; i<=nbFields; i++)
687     {
688       med_int ncomp=MEDfieldnComponent(fid,i);
689       INTERP_KERNEL::AutoPtr<char> comp=new char[ncomp*MED_SNAME_SIZE+1];
690       INTERP_KERNEL::AutoPtr<char> unit=new char[ncomp*MED_SNAME_SIZE+1];
691       INTERP_KERNEL::AutoPtr<char> dt_unit=new char[MED_LNAME_SIZE+1];
692       med_int nbPdt;
693       MEDfieldInfo(fid,i,nomcha,maa_ass,&localmesh,&typcha,comp,unit,dt_unit,&nbPdt);
694       std::string curFieldName=MEDLoaderBase::buildStringFromFortran(nomcha,MED_NAME_SIZE+1);
695       std::string curMeshName=MEDLoaderBase::buildStringFromFortran(maa_ass,MED_NAME_SIZE+1);
696       for (int k=1; k<=nbPdt; k++)
697         {
698           MEDfieldComputingStepInfo(fid,nomcha,k,&numdt,&numo,&dt);
699           if (MyGlobals::_Verbose>20) 
700             std::cout<< "on filename " << fileName << " field " << i << " fieldName " << curFieldName << " meshName " << curMeshName <<
701               " typ " << typcha << " nbComponent " << ncomp << " nbPdt " << nbPdt << " noPdt " << k <<
702               " ndt " << numdt << " nor " << numo << " dt " << dt << std::endl;
703           for (int ie=0; ie<lgentity; ie++)
704             {
705               for (int j=0; j<lggeom; j++)
706                 {
707                   med_int profilesize=0,nbi=0;
708                   med_entity_type enttype=ENTITYTYPE[ie];
709                   //enttype=MED_NODE;enttype=MED_CELL;enttype=MED_NODE_ELEMENT;
710                   char pflname[MED_NAME_SIZE+1]="";
711                   char locname[MED_NAME_SIZE+1]="";
712                   med_int nbofprofile=MEDfieldnProfile(fid,nomcha,numdt,numo,enttype,GEOMTYPE[j],pflname,locname);
713                   int profileit=1;
714                   if (enttype==MED_NODE)
715                     {
716                       med_geometry_type mygeomtype=MED_UNDEF_ENTITY_TYPE;
717                       med_int nbOfVal=MEDfieldnValueWithProfile(fid,nomcha,numdt,numo,enttype,mygeomtype,profileit,
718                                                                 MED_COMPACT_PFLMODE,pflname,&profilesize,locname,&nbi);
719                       if (nbOfVal>0)
720                         {
721                           if (MyGlobals::_Verbose>20)
722                             std::cout << "on filename " << fileName << " entity " << enttype << " nbOfVal with " <<
723                               nbofprofile << " profile(s) for geomType (AUCUN) nbOfVal " <<
724                               nbOfVal << " profilName '" << pflname << "' profileSize " << profilesize << " nbPtGauss " << nbi << std::endl;
725                           std::vector<std::string> resi;
726                           resi.push_back("idomain="); resi.back()+=IntToStr(idomain);
727                           resi.push_back("fileName="); resi.back()+=fileName;
728                           resi.push_back("meshName="); resi.back()+=curMeshName;
729                           resi.push_back("fieldName="); resi.back()+=curFieldName;
730                           resi.push_back("typeField="); resi.back()+=IntToStr((int)MEDCoupling::ON_NODES);
731                           resi.push_back("typeData="); resi.back()+=IntToStr((int)typcha);  //6 for double?
732                           resi.push_back("nbComponent="); resi.back()+=IntToStr((int)ncomp);
733                           resi.push_back("DT="); resi.back()+=IntToStr((int)numdt);
734                           resi.push_back("IT="); resi.back()+=IntToStr((int)numo);
735                           resi.push_back("time="); resi.back()+=DoubleToStr(dt);
736                           resi.push_back("entity="); resi.back()+=IntToStr((int)enttype);
737                           resi.push_back("entityName="); resi.back()+=ENTITYTYPENAME[ie];
738                           resi.push_back("nbOfVal="); resi.back()+=IntToStr((int)nbOfVal);
739                           resi.push_back("profilName="); resi.back()+=pflname;
740                           resi.push_back("profileSize="); resi.back()+=IntToStr((int)profilesize);
741                           resi.push_back("nbPtGauss="); resi.back()+=IntToStr((int)nbi);
742                           res.push_back(SerializeFromVectorOfString(resi));
743                         }
744                       break; //on nodes no need to scute all geomtype
745                     }
746                   else
747                     {
748                       med_geometry_type mygeomtype=GEOMTYPE[j];
749                       med_int nbOfVal=MEDfieldnValueWithProfile(fid,nomcha,numdt,numo,enttype,mygeomtype,profileit,
750                                                                 MED_COMPACT_PFLMODE,pflname,&profilesize,locname,&nbi);
751                       if (nbOfVal>0)
752                         {
753                           if (MyGlobals::_Verbose>20)
754                             std::cout << "on filename " << fileName << " entity " << enttype << " nbOfVal with " <<
755                               nbofprofile << " profile(s) for geomType " <<
756                               GEOMTYPE[j] << " " << GEOMTYPENAME[j] << " nbOfVal " <<
757                               nbOfVal << " profilName '" << pflname << "' profileSize " << profilesize << " nbPtGauss " << nbi << std::endl;
758                           int typeField=-1; //unknown
759                           if (enttype==MED_CELL)
760                             typeField=MEDCoupling::ON_CELLS;
761                           if (enttype==MED_NODE_ELEMENT)
762                             typeField=MEDCoupling::ON_GAUSS_NE;
763                           //if (enttype==??) typeField=ON_GAUSS_PT;
764                           std::vector<std::string> resi;
765                           resi.push_back("idomain="); resi.back()+=IntToStr(idomain);
766                           resi.push_back("fileName="); resi.back()+=fileName;
767                           resi.push_back("meshName="); resi.back()+=curMeshName;
768                           resi.push_back("fieldName="); resi.back()+=curFieldName;
769                           resi.push_back("typeField="); resi.back()+=IntToStr((int)typeField);
770                           resi.push_back("typeData="); resi.back()+=IntToStr((int)typcha);  //6 for double?
771                           resi.push_back("nbComponent="); resi.back()+=IntToStr((int)ncomp);
772                           resi.push_back("DT="); resi.back()+=IntToStr((int)numdt);
773                           resi.push_back("IT="); resi.back()+=IntToStr((int)numo);
774                           resi.push_back("time="); resi.back()+=DoubleToStr(dt);
775                           resi.push_back("entity="); resi.back()+=IntToStr((int)enttype);
776                           resi.push_back("entityName="); resi.back()+=ENTITYTYPENAME[ie];
777                           resi.push_back("geomType="); resi.back()+=IntToStr((int)GEOMTYPE[j]);
778                           resi.push_back("geomTypeName="); resi.back()+=GEOMTYPENAME[j];
779                           resi.push_back("nbOfVal="); resi.back()+=IntToStr((int)nbOfVal);
780                           resi.push_back("profilName="); resi.back()+=pflname;
781                           resi.push_back("profileSize="); resi.back()+=IntToStr((int)profilesize);
782                           resi.push_back("nbPtGauss="); resi.back()+=IntToStr((int)nbi);
783                           if (typeField==(-1))
784                             {
785                               std::cout << "WARNING : unknown typeField for entity type " << enttype << std::endl <<
786                                 SerializeFromVectorOfString(resi) << std::endl;
787                               continue;  //do not register push_back
788                             }
789                           res.push_back(SerializeFromVectorOfString(resi));
790                         }
791                     }
792                 }
793             }
794         }
795     }
796   delete [] maa_ass;
797   delete [] nomcha;
798   MEDfileClose(fid);
799   if (MyGlobals::_Verbose>10)
800     std::cout << "detected fields:\n" << ReprVectorOfString(res) << std::endl;
801   return res;
802 }
803
804 MEDCoupling::MCAuto< MEDCoupling::DataArrayInt32 > MEDPARTITIONER::FromIdTypeVec( const std::vector< mcIdType >& vec )
805 {
806   MEDCoupling::DataArrayInt32* array = MEDCoupling::DataArrayInt32::New();
807   array->alloc( vec.size(), 1 );
808   std::copy( vec.begin(), vec.end(), array->getPointer() );
809   return array;
810 }
811
812
813 /*!
814  * quick almost human readable information on all fields on a mesh in a .med file
815  */
816 std::vector<std::string> MEDPARTITIONER::BrowseAllFieldsOnMesh(const std::string& myfile, const std::string& mymesh, const int idomain)
817 {
818   std::vector<std::string> res=GetInfosOfField(myfile.c_str(),mymesh.c_str(),idomain);
819   return res;
820 }
821
822 /*!
823  * create empty MEDCouplingUMesh* dim 3
824  */
825 MEDCoupling::MEDCouplingUMesh* MEDPARTITIONER::CreateEmptyMEDCouplingUMesh()
826 {
827   MEDCoupling::MEDCouplingUMesh* umesh=MEDCoupling::MEDCouplingUMesh::New();
828   umesh->setMeshDimension(3);
829   umesh->allocateCells(0);
830   umesh->finishInsertingCells();
831   MEDCoupling::DataArrayDouble *myCoords=MEDCoupling::DataArrayDouble::New();
832   myCoords->alloc(0,3);
833   umesh->setCoords(myCoords);
834   umesh->setName("EMPTY");
835   myCoords->decrRef();
836   umesh->checkConsistencyLight();
837   return umesh;
838 }
839
840 namespace MEDPARTITIONER
841 {
842   BBTreeOfDim::BBTreeOfDim( std::size_t   dim,
843                             const double* bbs,
844                             mcIdType*     elems,
845                             int           level,
846                             mcIdType      nbelems,
847                             double        epsilon)
848   {
849     switch ( dim )
850       {
851       case 3:
852         _tree=new BBTree<3,mcIdType> (bbs,elems,level,nbelems,epsilon);
853         _PgetElementsAroundPoint = & BBTreeOfDim::_getElementsAroundPoint< 3 >;
854         _PgetIntersectingElems   = & BBTreeOfDim::_getIntersectingElems< 3 >;
855         break;
856       case 2:
857         _tree=new BBTree<2,mcIdType> (bbs,elems,level,nbelems,epsilon);
858         _PgetElementsAroundPoint = & BBTreeOfDim::_getElementsAroundPoint< 2 >;
859         _PgetIntersectingElems   = & BBTreeOfDim::_getIntersectingElems< 2 >;
860         break;
861       case 1:
862         _tree=new BBTree<1,mcIdType> (bbs,elems,level,nbelems,epsilon);
863         _PgetElementsAroundPoint = & BBTreeOfDim::_getElementsAroundPoint< 1 >;
864         _PgetIntersectingElems   = & BBTreeOfDim::_getIntersectingElems< 1 >;
865         break;
866       default:
867         _tree=0;
868         throw INTERP_KERNEL::Exception("BBTreeOfDim(): wrong space dimension");
869       }
870   }
871
872   BBTreeOfDim::~BBTreeOfDim()
873   {
874     delete (BBTree<3>*)_tree;
875   }
876
877   void BBTreeOfDim::getElementsAroundPoint( const double* coordsPtr,
878                                             std::vector<mcIdType>& elems ) const
879   {
880     BBTreeOfDim* me = (BBTreeOfDim*) this;
881     (me->*_PgetElementsAroundPoint) ( coordsPtr, elems );
882   }
883   void BBTreeOfDim::getIntersectingElems(const double* bb,
884                                          std::vector<mcIdType>& elems) const
885   {
886     BBTreeOfDim* me = (BBTreeOfDim*) this;
887     (me->*_PgetIntersectingElems) ( bb, elems );
888   }
889 }