Salome HOME
098bd1efe71013a1589694aeec4a3d54b5cd9821
[plugins/ghs3dprlplugin.git] / src / tepal2med / tetrahpc2med.cxx
1 // Copyright (C) 2007-2013  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.
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   : tetrahpc2med.cxx
22 // Author : Christian VAN WAMBEKE (CEA) 
23 // ---
24 //
25 /*
26 ** prog principal de ghs3dprl
27 */
28
29 #include <stdio.h> /* printf clrscr fopen fread fwrite fclose */
30 #include <string>
31 #include <cstring>
32 #include <cstdlib>
33 #include <iostream>
34 #include <sstream>
35 #include <fstream>
36 #include <vector>
37 #ifndef WIN32
38 #include <unistd.h>
39 #endif
40
41 #include <qstring.h>
42
43 #include <QXmlSimpleReader>
44 #include <QXmlInputSource>
45 #include <QApplication>
46
47 #include "ghs3dprl_msg_parser.h"
48 #include "dlg_ghs3dmain.h"
49
50 #ifdef WIN32
51 #include <io.h>
52 #include <windows.h>
53 #define F_OK 0
54 #endif
55
56 //#include "MEDMEM_Exception.hxx"
57 //#include "MEDMEM_define.hxx"
58
59 extern "C" {
60 #include <med.h>
61 //#include <med_config.h>
62 //#include <med_utils.h>
63 //#include <med_misc.h>
64 }
65
66 //************************************
67 med_idt ouvre_fichier_MED(char *fichier,int verbose)
68 {
69   med_idt fid = 0;
70   med_err ret = 0;
71   med_int majeur,mineur,release;
72
73   /* on regarde si le fichier existe */
74   ret = (int) access(fichier,F_OK);
75   if (ret < 0) return fid;
76
77   /* on regarde s'il s'agit d'un fichier au format HDF5 */
78   med_bool hdfok,medok;
79   ret = MEDfileCompatibility(fichier,&hdfok,&medok);
80   if (ret < 0){
81      std::cerr<<"File "<<fichier<<" not MED or HDF V5 formatted\n";
82      return fid;
83   }
84
85   /* Quelle version de MED est utilise par mdump ? */
86   MEDlibraryNumVersion(&majeur,&mineur,&release);
87   if (verbose>0)fprintf(stdout,"\nReading %s with MED V%d.%d.%d",
88                         fichier,majeur,mineur,release);
89
90   /* Ouverture du fichier MED en lecture seule */
91   fid = MEDfileOpen(fichier,MED_ACC_RDONLY);
92   if (ret < 0) return fid;
93
94   MEDfileNumVersionRd(fid, &majeur, &mineur, &release);
95   if (majeur < 2 || majeur == 2 && mineur < 2) {
96     fprintf(stderr,"File %s from MED V%d.%d.%d not assumed\n",
97                    fichier,majeur,mineur,release);
98     //" version est ant�ieure �la version 2.2";
99     ret = MEDfileClose(fid);
100     fid=0; }
101   else {
102     if (verbose>0)fprintf(stdout,", file from MED V%d.%d.%d\n",majeur,mineur,release); }
103
104   return fid;
105 }
106
107 //************************************
108 bool ReadFileMED(QString nomfilemed,ghs3dprl_mesh_wrap *mymailw)
109 {
110    med_err ret;
111    med_idt fid=0;
112    med_int i,j,sdim,mdim,nmaa,edim,majeur_lu,mineur_lu,release_lu,nprofils,nstep;
113    med_mesh_type type_maillage;
114    char dtunit[MED_SNAME_SIZE+1];
115    char axisname[MED_SNAME_SIZE+1];
116    char axisunit[MED_SNAME_SIZE*3+1];
117    med_sorting_type sortingtype;
118    med_axis_type axistype;
119    int numero=1;
120    QString key,tmp;
121    med_bool chan;
122    med_bool tran;
123    
124    //version qt3
125    char* chaine = (char*)malloc((nomfilemed.length()+1)*sizeof(char));
126    strncpy(chaine,nomfilemed.toLatin1().constData(),nomfilemed.length()+1);
127    //std::cout<<"*** ReadFileMED *** "<<chaine<<"\n";
128
129    fid=ouvre_fichier_MED(chaine,mymailw->verbose);
130    free(chaine);
131    if (fid == 0) {
132       std::cerr<<"Problem opening file "<<nomfilemed.toLatin1().constData()<<"\n";
133       return false;
134    }
135
136    nmaa = MEDnMesh(fid);
137    if (nmaa <= 0){
138       std::cerr<<"No meshes in "<<nomfilemed.toLatin1().constData()<<"\n";
139       ret = MEDfileClose(fid);
140       return false;
141    }
142    if (nmaa > 1) std::cout<<"More than one mesh in "<<nomfilemed.toLatin1().constData()<<", first one taken\n";
143    ret = MEDmeshInfo(fid,numero,mymailw->nommaa,&sdim,&mdim,&type_maillage,mymailw->maillage_description,
144                         dtunit,&sortingtype,&nstep,&axistype,axisname,axisunit);
145    if (ret < 0){
146       std::cerr<<"Problem MEDmeshInfo in "<<nomfilemed.toLatin1().constData()<<"\n";
147       ret = MEDfileClose(fid);
148       return false;
149    }
150    //changed with version med: a triangles mesh in 3d is dim 2 now and 3 before 2014
151    if (mdim != 2 && mdim != 3){
152       std::cerr<<"Problem mesh dimension should be 2 or 3: "<<mdim<<"\n";
153       ret = MEDfileClose(fid);
154       return false;
155    }
156    if (sdim != 3){
157       std::cerr<<"Problem space dimension should be 3: "<<sdim<<"\n";
158       ret = MEDfileClose(fid);
159       return false;
160    }
161    if (type_maillage != MED_UNSTRUCTURED_MESH){
162       std::cerr<<"Problem type mesh should be MED_NON_STRUCTURE: "<<type_maillage<<std::endl;
163       ret = MEDfileClose(fid);
164       return false;
165    }
166
167    //lecture nb de noeuds
168    //cf med-3.0.0_install/share/doc/html/maillage_utilisateur.html
169    med_int nnoe=MEDmeshnEntity(fid,mymailw->nommaa,MED_NO_DT,MED_NO_IT,
170       MED_NODE,MED_NO_GEOTYPE,MED_COORDINATE,MED_NO_CMODE,&chan,&tran);
171               //(med_geometrie_element)0,(med_connectivite)0);
172    if (nnoe<1){
173       std::cerr<<"Problem number of Vertices < 1\n";
174       ret = MEDfileClose(fid);
175       return false;
176    }
177
178    //nombre d'objets MED : mailles, faces, aretes , ... 
179    med_int nmailles[MED_N_CELL_GEO],nbtria3;
180    med_int nfaces[MED_N_FACE_GEO];
181    med_int naretes[MED_N_EDGE_FIXED_GEO],nbseg2;
182    //med_int nmailles[MED_NBR_GEOMETRIE_MAILLE],nbtria3;
183    //med_int nfaces[MED_NBR_GEOMETRIE_FACE];
184    //med_int naretes[MED_NBR_GEOMETRIE_ARETE],nbseg2;
185    //polygones et polyedres familles equivalences joints
186    med_int nmpolygones,npolyedres,nfpolygones,nfam,nequ,njnt;
187
188    //Combien de mailles, faces ou aretes pour chaque type geometrique ?
189    /*for (i=0;i<MED_NBR_GEOMETRIE_MAILLE;i++){
190       nmailles[i]=MEDnEntMaa(fid,mymailw->nommaa,MED_CONN,MED_MAILLE,typmai[i],typ_con);
191       //lecture_nombre_mailles_standards(fid,nommaa,typmai[i],typ_con,i);
192       if (mymailw->verbose>6) std::cout<<"NumberOf"<<nommai[i]<<"="<<nmailles[i]<<std::endl;
193    }*/
194    
195    nbtria3=MEDmeshnEntity(fid,mymailw->nommaa,MED_NO_DT,MED_NO_IT,
196       MED_CELL,MED_TRIA3,MED_CONNECTIVITY,MED_NODAL,&chan,&tran);
197    nbseg2=MEDmeshnEntity(fid,mymailw->nommaa,MED_NO_DT,MED_NO_IT,
198       MED_CELL,MED_SEG2,MED_CONNECTIVITY,MED_NODAL,&chan,&tran);
199
200    //combien de familles ?
201    nfam=MEDnFamily(fid,mymailw->nommaa);
202    if (mymailw->verbose>2) {
203       std::cout<<"\nNumberOfFamilies="<<nfam<<std::endl;
204       std::cout<<"NumberOfVertices="<<nnoe<<std::endl;
205       std::cout<<"NumberOfMED_SEG2="<<nbseg2<<std::endl;
206       std::cout<<"NumberOfMED_TRIA3="<<nbtria3<<"\n\n";
207    }
208    if (nbtria3<3){
209       std::cerr<<"Problem number of MED_TRIA3 < 3, not a skin of a volume\n";
210       ret = MEDfileClose(fid);
211       return false;
212    }
213
214 med_int ifamdelete=0,idelete;
215 std::vector<med_int> famdelete = std::vector<med_int>(nfam);
216 {
217   med_int ngro;
218   char *gro;
219   char nomfam[MED_NAME_SIZE+1];
220   med_int numfam;
221   char str1[MED_COMMENT_SIZE+1];
222   char str2[MED_LNAME_SIZE+1];
223   med_err ret = 0;
224   
225   for (i=0;i<nfam;i++) famdelete[i]=0;
226   for (i=0;i<nfam;i++) {
227
228     //nombre de groupes
229     ngro = MEDnFamilyGroup(fid,mymailw->nommaa,i+1);
230     if (ngro < 0){
231        std::cerr<<"Problem reading number of groups of family\n";
232        continue;
233     }
234
235     //atributs obsolete MED3
236     //allocation memoire par exces
237     gro = (char*) malloc(MED_LNAME_SIZE*(ngro+1));
238     
239     ret = MEDfamilyInfo(fid,mymailw->nommaa,i+1,nomfam,&numfam,gro);
240     if (ret < 0){
241        std::cerr<<"Problem reading informations of family\n";
242        continue;
243     }
244
245     if (mymailw->verbose>8) {
246      std::cout<<"Family "<<numfam<<" have "<<ngro<<" groups\n";
247      //affichage des resultats
248      for (j=0;j<ngro;j++) {
249       if (j==0) std::cout<<"  Groups :\n";
250       strncpy(str2,gro+j*MED_LNAME_SIZE,MED_LNAME_SIZE);
251       str2[MED_LNAME_SIZE] = '\0';
252       fprintf(stdout,"    name = %s\n",str2);
253      }
254      if (i==nfam-1) std::cout<<std::endl;
255     }
256     QString sfam,sgro;
257     sfam=sfam.sprintf("%d",numfam);
258     idelete=0;
259     for (j=0;j<ngro;j++){
260        strncpy(str2,gro+j*MED_LNAME_SIZE,MED_LNAME_SIZE);
261        str2[MED_LNAME_SIZE]='\0';
262        sgro=str2;
263        if (sgro.contains(mymailw->deletegroups)>0) {
264           //std::cout<<"idelete++ "<<sgro<<std::endl;
265           idelete++;
266        }
267     }
268
269     if (idelete==ngro && ngro>0) { //only delete family whith all delete groups
270        //std::cout<<"famdelete++ "<<numfam<<" "<<ifamdelete<<" "<<ngro<<std::endl;
271        famdelete[ifamdelete]=numfam;
272        ifamdelete++;
273     }
274
275     else {
276      for (j=0;j<ngro;j++){
277        strncpy(str2,gro+j*MED_LNAME_SIZE,MED_LNAME_SIZE);
278        str2[MED_LNAME_SIZE]='\0';
279        sgro=str2;
280        QRegExp qgroup=QRegExp("Group_Of_All",Qt::CaseSensitive,QRegExp::RegExp);
281        if (sgro.contains(mymailw->deletegroups)==0){
282           if (sgro.contains(qgroup)>0) {
283              sgro="Skin_"+sgro; //pas sur que ce soit pertinent
284           }
285           if (mymailw->verbose>8) std::cout<<"families.add("<<sfam.toLatin1().constData()<<
286                                         ","<<sgro.toLatin1().constData()<<")\n";
287           mymailw->families.add(sfam,sgro);
288        }
289        else {
290           //sgro="Skin_"+sgro; //pas sur que ce soit pertinent
291           //std::cout<<"--deletegroups matches \""<<sfam<<","<<sgro<<"\"\n";
292           if (mymailw->verbose>3) std::cout<<"--deletegroups matches \""<<
293                                         sgro.toLatin1().constData()<<
294                                         "\" in family "<<numfam<<std::endl;
295        }
296      }
297     }
298     
299     /*for (j=0;j<ngro;j++){
300        strncpy(str2,gro+j*MED_LNAME_SIZE,MED_LNAME_SIZE);
301        str2[MED_LNAME_SIZE]='\0';
302        sgro=str2;
303        //std::cout<<"families.add("<<sfam<<","<<sgro<<")\n";
304        if (sgro.contains(mymailw->deletegroups)==0){
305           //sgro="Skin_"+sgro; //pas sur que ce soit pertinent
306           std::cout<<"families.add("<<sfam<<","<<sgro<<")\n";
307           mymailw->families.add(sfam,sgro);
308        }
309        else {
310           std::cout<<"--deletegroups matches \""<<sgro<<"\"\n";
311           famdelete[ifamdelete]=numfam
312           ifamdelete++;
313        }
314     }*/
315
316     //on libere la memoire
317     free(gro);
318   }
319 }
320
321 //std::cout<<"famdelete"; for (j=0;j<ifamdelete;j++) std::cout<<" "<<famdelete[j]; std::cout<<std::endl;
322
323 if (mymailw->verbose>3){
324    std::cout<<"\nFamiliesAndGroupsOf "<<nomfilemed.toLatin1().constData()<<std::endl;
325    mymailw->families.write();
326 }
327    /* Allocations memoires */
328    /* table des coordonnees profil : (space dimension * nombre de noeuds ) */
329    med_float *coo=new med_float[nnoe*sdim];
330    /* table des numeros de familles des noeuds profil : (nombre de noeuds) */
331    med_int *famnodesskin=new med_int[nnoe];
332    //med_int *pfltab=new med_int[1]; //inutilise car on lit tout 
333    //lecture des noeuds : coordonnees
334    ret=MEDmeshNodeCoordinateRd(fid,mymailw->nommaa,MED_NO_DT,MED_NO_IT,MED_FULL_INTERLACE,coo);
335           //mdim,coo,mode_coo,MED_ALL,pfltab,0,&rep,mymailw->nomcoo,mymailw->unicoo);
336    if (ret < 0){
337       std::cerr<<"Problem reading nodes\n";
338       ret = MEDfileClose(fid);
339       //return false;
340    }
341    ret=MEDmeshEntityFamilyNumberRd(fid,mymailw->nommaa,MED_NO_DT,MED_NO_IT,MED_NODE,MED_NONE,famnodesskin);
342       //famnodesskin,nnoe,MED_NOEUD,(med_geometrie_element) 0);
343    if (ret < 0){
344       std::cerr<<"Problem reading families of nodes\n";
345       ret = MEDfileClose(fid);
346       return false;
347    }
348    if (mymailw->verbose>9) {
349      std::cout<<"\nVertices: no x y z family\n";
350      for (i=0;i<nnoe*mdim;i=i+3) {
351       fprintf(stdout,"%5d %13.5e %13.5e %13.5e %5d \n",
352           (i/3+1), coo[i], coo[i+1], coo[i+2], famnodesskin[i/3]);
353      } 
354      std::cout<<std::endl;
355    }
356
357    med_int *conn2=new med_int[nbseg2*2];
358    ret=MEDmeshElementConnectivityRd(fid,mymailw->nommaa,MED_NO_DT,MED_NO_IT,
359            MED_CELL,MED_SEG2,MED_NODAL,MED_FULL_INTERLACE,conn2);
360             //mdim,conn2,mode_coo,pfltab,0,MED_MAILLE,MED_SEG2,MED_NOD);
361    if (ret < 0){
362       std::cerr<<"Problem reading MED_SEG2\n";
363       ret = MEDfileClose(fid);
364       //return false;
365    }
366    med_int *famseg2skin=new med_int[nbseg2];
367    ret=MEDmeshEntityFamilyNumberRd(fid,mymailw->nommaa,MED_NO_DT,MED_NO_IT,MED_CELL,MED_SEG2,famseg2skin);
368       //MEDfamLire(fid,mymailw->nommaa,famseg2skin,nbseg2,MED_MAILLE,MED_SEG2);
369    if (ret < 0){
370       std::cerr<<"Problem reading families of MED_SEG2\n";
371       ret = MEDfileClose(fid);
372       return false;
373    }
374    if (mymailw->verbose>9) {
375      std::cout<<"\nConnectivity MED_SEG2: no node1 node2 family\n";
376      for (i=0;i<nbseg2*2;i=i+2) {
377       fprintf(stdout,"%5d %5d %5d %5d \n",
378           (i/2+1), conn2[i], conn2[i+1], famseg2skin[i/2]);
379      } 
380      std::cout<<std::endl;
381    }
382    //std::cout<<"\ncvw1 conn nbtria3 "<<nbtria3<<"dt "<<MED_NO_DT<<"it "<<MED_NO_IT<<"cell "<<MED_CELL<<"tria3 "<<MED_TRIA3<<std::endl;
383    med_int *conn3=new med_int[nbtria3*3];
384    ret=MEDmeshElementConnectivityRd(fid,mymailw->nommaa,MED_NO_DT,MED_NO_IT,
385            MED_CELL,MED_TRIA3,MED_NODAL,MED_FULL_INTERLACE,conn3);
386            //MEDconnLire(fid,mymailw->nommaa,mdim,conn3,mode_coo,pfltab,0,MED_MAILLE,MED_TRIA3,MED_NOD);
387    if (ret < 0){
388       std::cerr<<"Problem reading MED_TRIA3\n";
389       ret = MEDfileClose(fid);
390       //return false;
391    }
392    med_int *famtria3skin=new med_int[nbtria3];
393    ret=MEDmeshEntityFamilyNumberRd(fid,mymailw->nommaa,MED_NO_DT,MED_NO_IT,MED_CELL,MED_TRIA3,famtria3skin);
394         //MEDfamLire(fid,mymailw->nommaa,famtria3skin,nbtria3,MED_MAILLE,MED_TRIA3);
395    if (ret < 0){
396       std::cerr<<"Problem reading families of MED_TRIA3\n";
397       ret = MEDfileClose(fid);
398       return false;
399    }
400    if (mymailw->verbose>9) {
401      std::cout<<"\nConnectivity MED_TRIA3: no node1 node2 node3 family\n";
402      for (i=0;i<nbtria3*3;i=i+3) {
403       fprintf(stdout,"%5d %5d %5d %5d %5d \n",
404           (i/3+1), conn3[i], conn3[i+1], conn3[i+2], famtria3skin[i/3]);
405      } 
406      std::cout<<std::endl;
407    }
408
409   /*liberation memoire?
410   delete[] coo;
411   delete[] nomnoe;
412   delete[] numnoe;
413   delete[] nufano;*/
414
415   if (ifamdelete>0) {
416    //std::cout<<"!!!!!!!!nodes "<<famnodesskin[0]<<" "<<nnoe<<famdelete[1]<<std::endl;
417    for (i=0;i<nnoe;i++) {
418     for (j=0;j<ifamdelete;j++) {
419       if (famnodesskin[i]==famdelete[j]) {
420        //std::cout<<"nodes "<<famnodesskin[i]<<" "<<i<<" "<<famdelete[j]<<std::endl;
421        famnodesskin[i]=0; }
422     }
423    }
424    for (i=0;i<nbseg2;i++) {
425     for (j=0;j<ifamdelete;j++) {
426       if (famseg2skin[i]==famdelete[j]) famseg2skin[i]=0;
427     }
428    }
429    for (i=0;i<nbtria3;i++) {
430     for (j=0;j<ifamdelete;j++) {
431       if (famtria3skin[i]==famdelete[j]) famtria3skin[i]=0;
432     }
433    }
434   }
435    //stocks data for future use 
436    CVWtab *montab;
437    bool ok;
438
439    montab=new CVWtab(nnoe*mdim,coo);
440    tmp="SKIN_VERTICES_COORDINATES";
441    ok=mymailw->insert_key(tmp,montab);
442
443    montab=new CVWtab(nnoe,famnodesskin);
444    tmp="SKIN_VERTICES_FAMILIES";
445    ok=mymailw->insert_key(tmp,montab);
446    
447    montab=new CVWtab(nbseg2*2,conn2);
448    tmp="SKIN_SEG2_CONNECTIVITIES";
449    ok=mymailw->insert_key(tmp,montab);
450
451    montab=new CVWtab(nbtria3,famseg2skin);
452    tmp="SKIN_SEG2_FAMILIES";
453    ok=mymailw->insert_key(tmp,montab);
454
455    montab=new CVWtab(nbtria3*3,conn3);
456    tmp="SKIN_TRIA3_CONNECTIVITIES";
457    ok=mymailw->insert_key(tmp,montab);
458
459    montab=new CVWtab(nbtria3,famtria3skin);
460    tmp="SKIN_TRIA3_FAMILIES";
461    ok=mymailw->insert_key(tmp,montab);
462
463    //if (mymailw->verbose>6) ok=mymailw->list_keys_mesh_wrap();
464
465    ret = MEDfileClose(fid);
466    if (ret < 0){
467       std::cerr<<"Problem closing "<<nomfilemed.toLatin1().constData()<<"\n";
468       return false;
469    }
470    return true;
471 }
472
473
474 //************************************
475 int main(int argc, char *argv[])
476 {
477    bool ok;
478    int i,nb,nbfiles,limit_swap,nbelem_limit_swap,limit_swap_defaut,verbose;
479    QString path,pathini,casename,casenamemed,fileskinmed,
480            tmp,cmd,format,format_tetra,
481            test,menu,launchtetra,background,deletegroups,
482            ToMergeSubdomains,ToTagSubdomains,ToOutputInterfaces,ToDiscardSubdomains,
483            version="V3.0 (MED3+tetra-hpc)";
484    
485    char *chelp=NULL,
486         *ccasename=NULL,
487         *cnumber=NULL,
488         *cmedname=NULL,
489         *climitswap=NULL,
490         *cverbose=NULL,
491         *ctest=NULL,
492         *cmenu=NULL,
493         *claunchtetra=NULL,
494         *cToMergeSubdomains=NULL,
495         *cToTagSubdomains=NULL,
496         *cToOutputInterfaces=NULL,
497         *cToDiscardSubdomains=NULL,
498         *cbackground=NULL,
499         *cdeletegroups=NULL;
500
501    for (i = 0; i < argc; i++){
502       if (!strncmp (argv[i], "--help", sizeof ("--help"))) chelp = &(argv[i][0]);
503       else if (!strncmp (argv[i], "--casename=", sizeof ("--casename"))) ccasename = &(argv[i][sizeof ("--casename")]);
504       else if (!strncmp (argv[i], "--number=", sizeof ("--number"))) cnumber = &(argv[i][sizeof ("--number")]);
505       else if (!strncmp (argv[i], "--medname=", sizeof ("--medname"))) cmedname = &(argv[i][sizeof ("--medname")]);
506       else if (!strncmp (argv[i], "--limitswap=", sizeof ("--limitswap"))) climitswap = &(argv[i][sizeof ("--limitswap")]);
507       else if (!strncmp (argv[i], "--verbose=", sizeof ("--verbose"))) cverbose = &(argv[i][sizeof ("--verbose")]);
508       else if (!strncmp (argv[i], "--test=", sizeof ("--test"))) ctest = &(argv[i][sizeof ("--test")]);
509       else if (!strncmp (argv[i], "--menu=", sizeof ("--menu"))) cmenu = &(argv[i][sizeof ("--menu")]);
510       else if (!strncmp (argv[i], "--launchtetra=", sizeof ("--launchtetra"))) claunchtetra = &(argv[i][sizeof ("--launchtetra")]);
511       else if (!strncmp (argv[i], "--merge_subdomains=", sizeof ("--merge_subdomains"))) cToMergeSubdomains = &(argv[i][sizeof ("--")]);
512       else if (!strncmp (argv[i], "--tag_subdomains=", sizeof ("--tag_subdomains"))) cToTagSubdomains = &(argv[i][sizeof ("--")]);
513       else if (!strncmp (argv[i], "--output_interfaces=", sizeof ("--output_interfaces"))) cToOutputInterfaces = &(argv[i][sizeof ("--")]);
514       else if (!strncmp (argv[i], "--discard_subdomains=", sizeof ("--discard_subdomains"))) cToDiscardSubdomains = &(argv[i][sizeof ("--")]);
515       else if (!strncmp (argv[i], "--background=", sizeof ("--background"))) cbackground = &(argv[i][sizeof ("--background")]);
516       else if (!strncmp (argv[i], "--deletegroups=", sizeof ("--deletegroups"))) cdeletegroups = &(argv[i][sizeof ("--deletegroups")]);
517       }
518
519    if (argc < 2 || chelp){
520       std::cout<<"tetrahpc2med "<<version.toLatin1().constData()<<" Available options:\n"
521       "   --help               : produces this help message\n"<<
522       "   --casename           : path and name of input tetrahpc2med files which are\n"<<
523       "                           - output files of GHS3DPRL_Plugin .mesh\n"<<
524       "                           - output file of GHS3DPRL_Plugin casename_skin.med (optional)\n"<<
525       "                          with initial skin and its initial groups\n"<<
526       "   --number             : number of partitions\n"<<
527       "   --medname            : path and name of output MED files\n"<<
528       "   --limitswap          : max size of working cpu memory (Mo) (before swapping on .temp files)\n"<<
529       "   --verbose            : trace of execution (0->6)\n"<<
530       "   --test               : more tests about joints, before generation of output files\n"<<
531       "   --menu               : a GUI menu for option number\n"<<
532       "   --launchtetra        : also launch tetra-hpc on files casename.mesh and option number\n"<<
533       "   --merge_subdomains   : merge the subdomains into one mesh and write the output .mesh(b) file\n"<<
534       "   --tag_subdomains     : use the parallel subdomain index as tag into the merged output mesh\n"<<
535       "                            to identify the parallel subdomains (used in combination with the merge_subdomains option)\n"<<
536       "   --output_interfaces  : write the parallel subdomains interface triangles into the merged output mesh\n"<<
537       "                            (used in combination with the merge_subdomains option)\n"<<
538       "   --discard_subdomains : discard the parallel subdomains informations output (mesh, global numbering and interfaces)\n"<<
539       "   --background         : force background mode from launch tetra-hpc and generation of final MED files (big meshes)\n"<<
540       "   --deletegroups       : regular expression (see QRegExp) which matches unwanted groups in final MED files\n"<<
541       "                            (try --deletegroups=\"(\\bJOINT)\"\n"<<
542       "                            (try --deletegroups=\"(\\bAll_Nodes|\\bAll_Faces)\"\n"<<
543       "                            (try --deletegroups=\"((\\bAll_|\\bNew_)(N|F|T))\"\n";
544       std::cout<<"example:\n   tetrahpcl2med --casename=/tmp/GHS3DPRL --number=2 --medname=DOMAIN "<<
545                  "--limitswap=1000 --verbose=0 --test=yes --menu=no --launchtetra=no\n\n";
546       return 1;  //no output files
547    }
548    
549    if (!ccasename){
550       std::cerr<<"--casename: a path/name is expected\n\n";
551       return 1;
552    }
553    casename=ccasename;
554    if (!cnumber){
555       std::cerr<<"--number: an integer is expected\n\n";
556       return 1;
557    }
558    tmp=cnumber;
559    nbfiles=tmp.toLong(&ok,10);
560    if (!ok){
561       std::cerr<<"--number: an integer is expected\n\n";
562       return 1;
563    }
564    if (nbfiles<=0){
565       std::cerr<<"--number: a positive integer is expected\n\n";
566       return 1;
567    }
568    if (nbfiles>2048){ //delirium in 2014
569       std::cerr<<"--number: a positive integer <= 2048 is expected\n\n";
570       return 1;
571    }
572    if (!cmedname) cmedname=ccasename;
573    casenamemed=cmedname;
574    limit_swap_defaut=1000; //1000Mo
575    limit_swap=limit_swap_defaut;
576    if (climitswap){
577       tmp=climitswap;
578       limit_swap=tmp.toLong(&ok,10);
579       if (!ok){
580          std::cerr<<"--limitswap: an integer is expected. try 1000\n\n";
581          return 1;
582       }
583       if (limit_swap<1 || limit_swap>32000){
584          std::cerr<<"--limitswap: [1->32000] expected. try 1000\n\n";
585          return 1;
586       }
587    }
588    //default 1GOctet/8(for float)
589    nbelem_limit_swap=limit_swap*1000000; //100%
590    CVWtab::memorymax=nbelem_limit_swap;
591
592    verbose=1; //default
593    if (cverbose){
594       tmp=cverbose;
595       verbose=tmp.toLong(&ok,10);
596       if (!ok){
597          std::cerr<<"--verbose: an integer is expected\n\n";
598          return 1;
599       }
600       if (verbose<0){
601          std::cerr<<"--verbose: a positive integer is expected\n\n";
602          return 1;
603       }
604    }
605
606    test="no"; //default
607    if (ctest){
608       tmp=ctest;
609       if (tmp=="yes") test="yes";
610    }
611
612    menu="no"; //default
613    if (cmenu){
614       tmp=cmenu;
615       if (tmp=="yes") menu="yes";
616    }
617
618    launchtetra="no"; //default
619    if (claunchtetra){
620       tmp=claunchtetra;
621       if (tmp=="yes") launchtetra="yes";
622    }
623
624    ToMergeSubdomains="no"; //default
625    if (cToMergeSubdomains){
626       tmp=cToMergeSubdomains;
627       if (tmp=="yes") ToMergeSubdomains="yes";
628    }
629
630    ToTagSubdomains="no"; //default
631    if (cToTagSubdomains){
632       tmp=cToTagSubdomains;
633       if (tmp=="yes") ToTagSubdomains="yes";
634    }
635
636    ToOutputInterfaces="no"; //default
637    if (cToOutputInterfaces){
638       tmp=cToOutputInterfaces;
639       if (tmp=="yes") ToOutputInterfaces="yes";
640    }
641
642    ToDiscardSubdomains="no"; //default
643    if (cToDiscardSubdomains){
644       tmp=cToDiscardSubdomains;
645       if (tmp=="yes") ToDiscardSubdomains="yes";
646    }
647
648    background="no"; //default
649    if (cbackground){
650       tmp=cbackground;
651       if (tmp=="yes") background="yes";
652    }
653
654
655    // We must always have an application
656    if (menu=="yes") {
657     QApplication a(argc,argv);
658     dlg_ghs3dmain *m = new dlg_ghs3dmain();
659     m->setWindowTitle("tetrahpc2med 3.0");
660     m->show();
661     a.exec();
662     if ( m->result() == QDialog::Accepted ) {
663       std::cout<<"parameters "<<m->KeepFiles()<<" "<<m->NbPart()<<std::endl;
664       nbfiles=m->NbPart();
665     }
666     else {
667       return 1;
668     }
669     delete m;
670    }
671
672    int n=casenamemed.count('/');
673    if (n>0)
674       path=casenamemed.section('/',-n-1,-2)+"/";
675    else
676       path="./";
677       casenamemed=casenamemed.section('/',-1);
678    if (casenamemed.length()>20){
679       std::cerr<<"--medname truncated (no more 20 characters)"<<std::endl;
680       casenamemed.truncate(20);
681    }
682
683    n=casename.count('/');
684    if (n>0)
685       pathini=casename.section('/',-n-1,-2)+"/";
686    else
687       pathini="./";
688       casename=casename.section('/',-1);
689    if (casename.length()>20){
690       std::cerr<<"--casename truncated (no more 20 characters)"<<std::endl;
691       casename.truncate(20);
692    }
693
694    /*std::cout<<"CaseNameMed="<<casenamemed<<std::endl;
695    std::cout<<"PathMed="<<path<<std::endl;*/
696
697    deletegroups="(\\bxyz)"; //default improbable name
698    if (cdeletegroups){
699       deletegroups=cdeletegroups;
700    }
701    
702    //verbose=5;
703    if (verbose>0)
704    std::cout<<"tetrahpc2med "<<version.toLatin1().constData()<<" parameters:"<<
705          "\n   --casename="<<pathini.toLatin1().constData()<<casename.toLatin1().constData()<<
706          "\n   --number="<<nbfiles<<
707          "\n   --medname="<<path.toLatin1().constData()<<casenamemed.toLatin1().constData()<<
708          "\n   --limitswap="<<limit_swap<<
709          "\n   --verbose="<<verbose<<
710          "\n   --test="<<test.toLatin1().constData()<<
711          "\n   --menu="<<menu.toLatin1().constData()<<
712          "\n   --launchtetra="<<launchtetra.toLatin1().constData()<<
713          "\n   --merge_subdomains="<<ToMergeSubdomains.toLatin1().constData()<<
714          "\n   --tag_subdomains="<<ToTagSubdomains.toLatin1().constData()<<
715          "\n   --output_interfaces="<<ToOutputInterfaces.toLatin1().constData()<<
716          "\n   --discard_subdomains="<<ToDiscardSubdomains.toLatin1().constData()<<
717          "\n   --background="<<background.toLatin1().constData()<<
718          "\n   --deletegroups=\""<<deletegroups.toLatin1().constData()<<"\"\n";
719    
720    //utile si appel par plugin ghs3dprl sur big meshes et tetrahpc sur plusieurs jours
721 #ifndef WIN32
722    if (background=="yes"){
723       pid_t pid = fork();
724       if (pid > 0) {
725          //Process father
726          exit(0); //temporary ok for plugin
727       }
728       //process children
729       //On rend le fils independant de tout terminal
730       //from here everything in background: tetrahpc AND generation of final MED files
731       setsid();
732       system("sleep 10");  //for debug
733    }
734 #else
735    printf("background mode is not supported on win32 platform !\n");
736 #endif
737
738    //"tetrahpc -f exemple1 -n 4"
739    if (launchtetra=="yes"){
740       //tetra_hpc.exe --help
741       //mpirun -n 3 mg-tetra_hpc.exe --in GHS3DPRL.mesh --out TOTO.mesh
742       
743       //direct mpirun cause problem: invalid
744       //cmd="mpirun -n "+cmd.sprintf("%d",nbfiles)+" mg-tetra_hpc.exe --in "+
745       
746       //call tetra_hpc.bash is script which assumes mpirun after compilation openmpi etc...
747       cmd="mg-tetra_hpc.bash -n "+cmd.sprintf("%d",nbfiles)+" --in "+
748           pathini+casename+".mesh --out "+
749           pathini+casename+".mesh"+
750           " --merge_subdomains "+ToMergeSubdomains+
751           " --tag_subdomains "+ToTagSubdomains+
752           " --output_interfaces "+ToOutputInterfaces+
753           " --discard_subdomains "+ToDiscardSubdomains+
754           " > "+path+"tetrahpc.log";
755       std::cout<<"\nlaunchtetra command: background="<<cbackground<<
756                  "\n      "<<cmd.toLatin1().constData()<<std::endl;
757       system(cmd.toLatin1().constData()); // run
758       //sometimes it is better to wait flushing files on slow filesystem...
759       system("sleep 3");
760    }
761    ghs3dprl_mesh_wrap *mymailw=new ghs3dprl_mesh_wrap;
762    //no constructor, later maybe
763    mymailw->nbfiles=0;
764    mymailw->nbfilestot=nbfiles;
765    //for huge cases big array swap in huge binary files
766    mymailw->nbelem_limit_swap=nbelem_limit_swap;
767    mymailw->verbose=verbose;
768    mymailw->casename=casename;
769    mymailw->medname=casenamemed;
770    mymailw->path=path;
771    mymailw->pathini=pathini;
772    mymailw->deletegroups=QRegExp(deletegroups,Qt::CaseSensitive,QRegExp::RegExp);
773    ghs3dprl_msg_parser handler;
774    //constructor later maybe
775    //handler.verbose=true;
776    handler.mailw=mymailw;
777    mymailw->families.no=1;
778    //std::cout<<"coucou1 "<<mymailw->families.no<<std::endl;
779    //mymailw->families.add(casename,casenamemed);
780    format=format.sprintf("%d",nbfiles);
781    int nbf=format.length();
782    format=format.sprintf(".%%0%dd.%%0%dd",nbf,nbf);
783    format_tetra=".%05d";
784    if (verbose>10)std::cout<<"format "<<format.toLatin1().constData()<<std::endl;
785    if (verbose>10)std::cout<<"format_tetra "<<format_tetra.toLatin1().constData()<<std::endl;
786    mymailw->format=format;
787    mymailw->format_tetra=format_tetra;
788    mymailw->for_tetrahpc=true; //to know what files to read: .noboite or .mesh
789    
790    //something like "/home/wambeke/tmp/GHS3DPRL_skin.med"
791    fileskinmed=pathini+casename+"_skin.med";
792    //fileskinmed="/home/wambeke/tmp/GHS3DPRL_skin.med";
793    /*for debug
794    {
795    char ctmp[fileskinmed.length()+1] ; strcpy(ctmp,fileskinmed);
796    int res=dumpMED(&ctmp[0],1);
797    }*/
798    int ret = access(fileskinmed.toLatin1().constData(),F_OK); //on regarde si le fichier existe
799    if (ret >= 0) {
800       ok=ReadFileMED(fileskinmed,mymailw); }
801    else {
802       if (verbose>0)std::cout<<"Initial skin file <"<<fileskinmed.toLatin1().constData()<<"> does not exist\n"; }
803    
804
805 //if test quickly read all files before (or only small files)
806  if (test=="yes"){
807    if (verbose>0) std::cout<<"\nReading output files of tetrahpc as input files of tetrahpc2med...\n";
808    //only read beginning of files .xxxxx.mesh
809    //supposed big files big arrays so only see first lines
810    mymailw->nbfiles=0;
811    for (int i=1; i<=nbfiles; i++){
812       mymailw->nofile=i;
813       tmp=pathini+casename+tmp.sprintf(format_tetra.toLatin1().constData(),i)+".mesh";
814       if (verbose>0) std::cout<<"FileName="<<tmp.toLatin1().constData()<<std::endl;
815       ok=mymailw->TestExistingFileMESHnew(tmp);
816    }
817    if (verbose>0)
818       std::cout<<"NumberOfFilesMESHTested="<<mymailw->nbfiles<<": ok\n\n";
819    if (mymailw->nbfiles != nbfiles){
820       std::cerr<<"NumberOfFiles != NumberOfFilesTested is unexpected\n\n";
821       return 1;
822    }
823  }  //end if test
824  
825    ok=mymailw->Write_MEDfiles_v2(true); //deletekeys=true
826    
827    nb=mymailw->remove_all_keys_mesh_wrap();
828    if (verbose>3)std::cout<<"***remove_all_key_mesh_wrap*** "<<nb<<" keys removed\n";
829    if (verbose>0)std::cout<<std::endl<<"===end of "<<argv[0]<<"==="<<std::endl;
830
831    //for debug
832    //int res=dumpMED("/home/wambeke/tmp/DOMAIN_1.med",1);
833
834    return 0; //ok
835 }