Back to index

salome-med  6.5.0
medpartitioner.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D
00002 //
00003 // This library is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public
00005 // License as published by the Free Software Foundation; either
00006 // version 2.1 of the License.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public
00014 // License along with this library; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00016 //
00017 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00018 //
00019 
00020 /*
00021   examples of launch
00022   export verb=1
00023   medpartitioner --input-file=blade.med --output-file=ttmp1_ --ndomains=2 --dump-cpu-memory --verbose=$verb
00024   medpartitioner --input-file=medpartitioner_blade.xml --output-file=ttmp1_ --ndomains=2 --dump-cpu-memory --verbose=$verb
00025   medpartitioner --input-file=ttmp1_.xml --output-file=tttmp1_ --ndomains=4 --dump-cpu-memory --verbose=$verb
00026 */
00027 
00028 /*
00029 #include "MEDPARTITIONER_Graph.hxx"
00030 #include "MEDPARTITIONER_Topology.hxx"
00031 #include "MEDPARTITIONER_ParaDomainSelector.hxx"
00032 #include "MEDPARTITIONER_MeshCollection.hxx"
00033 #include "MEDPARTITIONER_Utils.hxx"
00034 */
00035 
00036 #include "MEDPARTITIONER_MeshCollection.hxx"
00037 #include "MEDPARTITIONER_ParallelTopology.hxx"
00038 #include "MEDPARTITIONER_ParaDomainSelector.hxx"
00039 #include "MEDPARTITIONER_Utils.hxx"
00040 
00041 #include <string>
00042 #include <fstream>
00043 #include <cstring>
00044 #include <cstdlib>
00045 #include <iostream>
00046 
00047 using namespace std;
00048 using namespace MEDPARTITIONER;
00049 
00050 int main(int argc, char** argv)
00051 {
00052 #if !defined(MED_ENABLE_METIS) && !defined(MED_ENABLE_SCOTCH)
00053   std::cout << "Sorry, no one split method is available. Please, compile with METIS or SCOTCH." << std::endl;
00054   return 1;
00055 #else
00056 
00057   // Defining options
00058   // by parsing the command line
00059   
00060   bool split_family=false;
00061   bool empty_groups=false;
00062   bool mesure_memory=false;
00063   bool filter_face=true;
00064 
00065   string input;
00066   string output;
00067   string meshname;
00068   string library="metis";  //default
00069   int ndomains;
00070   int help=0;
00071   
00072   //sequential : no MPI
00073   MyGlobals::_World_Size=1;
00074   MyGlobals::_Rank=0;
00075 
00076   // Primitive parsing of command-line options
00077   string desc ("Available options of medpartitioner V1.0:\n"
00078                "\t--help                   : produces this help message\n"
00079                "\t--verbose                : echoes arguments\n"
00080                "\t--input-file=<string>    : name of the input .med file or .xml master file\n"
00081                "\t--output-file=<string>   : name of the resulting file (without extension)\n"
00082                "\t--ndomains=<number>      : number of subdomains in the output file, default is 1\n"
00083 #if defined(MED_ENABLE_METIS) && defined(MED_ENABLE_SCOTCH)
00084   //user can choose!
00085                "\t--split-method=<string>  : name of the splitting library (metis/scotch), default is metis\n"
00086 #endif
00087 //               "\t--creates-boundary-faces : creates boundary faces mesh in the output files\n"
00088                "\t--dump-cpu-memory        : dumps passed CPU time and maximal increase of used memory\n"
00089                );
00090 
00091   if (argc<=1) help=1;
00092   string value;
00093   for (int i = 1; i < argc; i++)
00094     {
00095       if (strlen(argv[i]) < 3) 
00096         {
00097           cerr << "bad argument : "<< argv[i] << endl;
00098           return 1;
00099         }
00100     
00101       if (TestArg(argv[i],"--verbose",value)) 
00102         {
00103           MyGlobals::_Verbose=1;
00104           if (value!="") MyGlobals::_Verbose = atoi(value.c_str());
00105         }
00106       else if (TestArg(argv[i],"--help",value)) help=1;
00107 //      else if (TestArg(argv[i],"--test",value)) test=1;
00108       else if (TestArg(argv[i],"--input-file",value)) input=value;
00109       else if (TestArg(argv[i],"--output-file",value)) output=value;
00110       else if (TestArg(argv[i],"--split-method",value)) library=value;
00111       else if (TestArg(argv[i],"--ndomains",value)) ndomains=atoi(value.c_str());
00112 //      else if (TestArg(argv[i],"--creates-boundary-faces",value)) MyGlobals::_Creates_Boundary_Faces=1;
00113       else if (TestArg(argv[i],"--dump-cpu-memory",value)) mesure_memory=true;
00114       else 
00115         {
00116           cerr << "unknown argument : "<< argv[i] << endl;
00117           return 1;
00118         }
00119     }
00120 
00121   MyGlobals::_Is0verbose=MyGlobals::_Verbose;
00122   
00123 //no choice
00124 #if defined(MED_ENABLE_METIS) && !defined(MED_ENABLE_SCOTCH)
00125   library = "metis";
00126 #endif
00127 #if !defined(MED_ENABLE_METIS) && defined(MED_ENABLE_SCOTCH)
00128   library = "scotch";
00129 #endif
00130 //user choice
00131 #if defined(MED_ENABLE_METIS) && defined(MED_ENABLE_SCOTCH)
00132   if ((library!="metis") && (library!="scotch"))
00133     {
00134       cerr << "split-method only available : metis, scotch" << endl;
00135       return 1;
00136     }
00137 #endif
00138  
00139   if (help==1)
00140     {
00141       cout<<desc<<"\n";
00142       return 0;
00143     }
00144   
00145   if (MyGlobals::_Is0verbose)
00146     {
00147       cout << "medpartitioner V1.0 :" << endl;
00148       cout << "  input-file = " << input << endl;
00149       cout << "  output-file = " << output << endl;
00150       cout << "  split-method = " << library << endl;
00151       cout << "  ndomains = " << ndomains << endl;
00152 //      cout << "  creates_boundary_faces = " << MyGlobals::_Creates_Boundary_Faces << endl;
00153       cout << "  dump-cpu-memory = " << mesure_memory<< endl;
00154       cout << "  verbose = " << MyGlobals::_Verbose << endl;
00155     }
00156   //testing whether it is possible to write a file at the specified location
00157   if (MyGlobals::_Rank==0)
00158     {
00159       string outputtest = output + ".testioms.";
00160       ofstream testfile (outputtest.c_str());
00161       if (testfile.fail())
00162         { 
00163           cerr << "output-file directory does not exist or is in read-only access" << endl;
00164           return 1;
00165         }
00166       //deletes test file
00167       remove(outputtest.c_str());
00168     }
00169   
00170   // Beginning of the computation
00171 
00172   // Loading the mesh collection
00173   if (MyGlobals::_Is0verbose) cout << "Reading input files "<<endl;
00174   
00175   try
00176     {
00177       /*MEDPARTITIONER::ParaDomainSelector parallelizer(mesure_memory);
00178       MEDPARTITIONER::MeshCollection collection(input,parallelizer);
00179       MEDPARTITIONER::ParallelTopology* aPT = (MEDPARTITIONER::ParallelTopology*) collection.getTopology();
00180       aPT->setGlobalNumerotationDefault(collection.getParaDomainSelector());
00181       //int nbfiles=MyGlobals::_fileMedNames->size(); //nb domains
00182       //to have unique valid fields names/pointers/descriptions for partitionning
00183       collection.prepareFieldDescriptions();
00184       //int nbfields=collection.getFieldDescriptions().size(); //on all domains
00185       //cout<<ReprVectorOfString(collection.getFieldDescriptions());
00186     
00187       if (MyGlobals::_Is0verbose)
00188         {
00189           cout<<"fileNames :"<<endl
00190               <<ReprVectorOfString(MyGlobals::_File_Names);
00191           cout<<"fieldDescriptions :"<<endl
00192               <<ReprFieldDescriptions(collection.getFieldDescriptions()," "); //cvwat07
00193           cout<<"familyInfo :\n"
00194               <<ReprMapOfStringInt(collection.getFamilyInfo())<<endl;
00195           cout<<"groupInfo :\n"
00196               <<ReprMapOfStringVectorOfString(collection.getGroupInfo())<<endl;
00197         }*/
00198       MEDPARTITIONER::ParaDomainSelector parallelizer(mesure_memory);
00199       MEDPARTITIONER::MeshCollection collection(input,parallelizer);
00200       MEDPARTITIONER::ParallelTopology* aPT = (MEDPARTITIONER::ParallelTopology*) collection.getTopology();
00201       aPT->setGlobalNumerotationDefault(collection.getParaDomainSelector());
00202       //to have unique valid fields names/pointers/descriptions for partitionning
00203       collection.prepareFieldDescriptions();
00204       
00205       //MEDPARTITIONER::MeshCollection collection(input);
00206 
00207       //Creating the graph and partitioning it
00208       if (MyGlobals::_Is0verbose) cout << "Computing partition with " << library << endl;
00209   
00210       auto_ptr< MEDPARTITIONER::Topology > new_topo;
00211       if (library == "metis")
00212         new_topo.reset( collection.createPartition(ndomains,MEDPARTITIONER::Graph::METIS));
00213       else
00214         new_topo.reset( collection.createPartition(ndomains,MEDPARTITIONER::Graph::SCOTCH));
00215       parallelizer.evaluateMemory();
00216   
00217       //Creating a new mesh collection from the partitioning
00218       if (MyGlobals::_Is0verbose)  cout << "Creating new meshes"<< endl;
00219       MEDPARTITIONER::MeshCollection new_collection(collection,new_topo.get(),split_family,empty_groups);
00220   
00221       if (filter_face) new_collection.filterFaceOnCell();
00222     
00223       //to get infos on all procs
00224     
00225       //see meshName
00226       vector<string> finalInformations;
00227       vector<string> r1,r2;
00228       //r1=AllgathervVectorOfString(MyGlobals::_General_Informations);
00229       r1=MyGlobals::_General_Informations;
00230       //if (MyGlobals::_Is0verbose>1000) cout << "generalInformations : \n"<<ReprVectorOfString(r1);
00231       r2=SelectTagsInVectorOfString(r1,"ioldDomain=");
00232       r2=SelectTagsInVectorOfString(r2,"meshName=");
00233       if (r2.size()==(collection.getMesh()).size())
00234         {
00235           for (std::size_t i=0; i<r2.size(); i++)
00236             r2[i]=EraseTagSerialized(r2[i],"ioldDomain=");
00237           r2=DeleteDuplicatesInVectorOfString(r2);
00238           if (r2.size()==1)
00239             {
00240               string finalMesh="finalMeshName="+ExtractFromDescription(r2[0], "meshName=");
00241               finalInformations.push_back(SerializeFromString(finalMesh));
00242             }
00243         }
00244       if (finalInformations.size()==0)
00245         {
00246           if (MyGlobals::_Rank==0)
00247             cerr<<"Problem on final meshName : set at 'Merge'"<<endl;
00248           finalInformations.push_back(SerializeFromString("finalMeshName=Merge"));
00249         }
00250     
00251       //see field info nbComponents & componentInfo (if fields present)
00252       r2=SelectTagsInVectorOfString(r1,"fieldName=");
00253       r2=SelectTagsInVectorOfString(r2,"nbComponents=");
00254       //may be yes? or not?
00255       for (std::size_t i=0; i<r2.size(); i++)
00256         r2[i]=EraseTagSerialized(r2[i],"ioldFieldDouble=");
00257       r2=DeleteDuplicatesInVectorOfString(r2);
00258       for (std::size_t i=0; i<r2.size(); i++)
00259         finalInformations.push_back(r2[i]);
00260     
00261       MyGlobals::_General_Informations=finalInformations;
00262       if (MyGlobals::_Is0verbose) 
00263         cout << "generalInformations : \n"<<ReprVectorOfString(finalInformations);
00264     
00265       //new_collection.setSubdomainBoundaryCreates(creates_boundary_faces);
00266       if (MyGlobals::_Is0verbose) cout << "Writing "<<ndomains<<" output files "<<output<<"xx.med"<<" and "<<output<<".xml"<<endl;
00267       new_collection.write(output);
00268   
00269       /*if ( mesure_memory )
00270         if ( parallelizer.isOnDifferentHosts() || MyGlobals::_Rank==0 )
00271           {
00272             cout << "Elapsed time = " << parallelizer.getPassedTime()
00273                  << ", max memory usage = " << parallelizer.evaluateMemory() << " KB"
00274                  << endl;
00275           }*/
00276       
00277       if (MyGlobals::_Is0verbose>0) cout<<"OK END"<< endl;
00278       return 0;
00279     }
00280   catch(const char *mess)
00281     {
00282       cerr<<mess<<endl;
00283       fflush(stderr);
00284       return 1;
00285     }
00286   catch(INTERP_KERNEL::Exception& e)
00287     {
00288       cerr<<"INTERP_KERNEL_Exception : "<<e.what()<<endl;
00289       fflush(stderr);
00290       return 1;
00291     }
00292   catch(std::exception& e)
00293     {
00294       cerr<<"std_Exception : "<<e.what()<<endl;
00295       fflush(stderr);
00296       return 1;
00297     }
00298   catch(...)
00299     {
00300       cerr<<"an unknown type exception error was occured"<<endl;
00301       fflush(stderr);
00302       return 1;
00303     }
00304 #endif
00305 }