Back to index

salome-med  6.5.0
medsplitter_para.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 //  MED medsplitter : tool to split n MED files into p separate 
00021 //                    MED files with a partitioning specified 
00022 //                    by an external tool
00023 //  File   : medsplitter.cxx
00024 //  Module : MED
00025 //
00026 
00027 #include "MEDSPLITTER_MESHCollection.hxx"
00028 #include "MEDSPLITTER_Topology.hxx"
00029 #include "MEDSPLITTER_ParaDomainSelector.hxx"
00030 
00031 #include "MEDMEM_STRING.hxx"
00032 
00033 #include <mpi.h>
00034 
00035 #include <fstream>
00036 
00037 #ifdef BOOST_PROGRAM_OPTIONS_LIB
00038 #include <boost/program_options.hpp>
00039 namespace po=boost::program_options;
00040 #endif
00041 
00042 using namespace std;
00043 
00044 
00045 
00046 int main(int argc, char** argv)
00047 {
00048 #ifndef MED_ENABLE_PARMETIS
00049 #ifndef ENABLE_PTSCOTCH
00050   cout << "Sorry, no one split method is available. Please, compile with ParMETIS or PT-SCOTCH."<<endl;
00051   return 1;
00052 #endif
00053 #endif
00054 
00055   // Defining options
00056   // by parsing the command line
00057   //bool mesh_only = false;
00058   //bool is_sequential = true;
00059   bool xml_output_master=true;
00060   bool creates_boundary_faces=false;  
00061   bool split_family=false;
00062   bool empty_groups=false;
00063   bool mesure_memory=false;
00064 
00065   string input;
00066   string output;
00067   string meshname;
00068   string library;
00069   int ndomains;
00070 
00071 #ifdef BOOST_PROGRAM_OPTIONS_LIB
00072 
00073   // Use boost::program_options for command-line options parsing
00074 
00075   po::options_description desc("Available options");
00076   desc.add_options()
00077     ("help","produces this help message")
00078     //("mesh-only","prevents the splitter from creating the fields contained in the original file(s)")
00079     //("distributed","specifies that the input file is distributed")
00080     ("input-file",po::value<string>(),"name of the input MED file")
00081     ("output-file",po::value<string>(),"name of the resulting file")
00082     //("meshname",po::value<string>(),"name of the input mesh")
00083 #ifdef MED_ENABLE_PARMETIS
00084 #ifdef ENABLE_PTSCOTCH
00085     ("split-method",po::value<string>(&library)->default_value("metis"),"name of the splitting library (metis,scotch)")
00086 #endif
00087 #endif
00088     ("ndomains",po::value<int>(&ndomains)->default_value(1),"number of subdomains in the output file")
00089     ("plain-master","creates a plain masterfile instead of an XML file")
00090     ("creates-boundary-faces","creates the necessary faces so that faces joints are created in the output files")
00091     ("family-splitting","preserves the family names instead of focusing on the groups")
00092     ("empty-groups","creates empty groups in zones that do not contain a group from the original domain")
00093     ("dump-cpu-memory","dumps passed CPU time and maximal increase of used memory");
00094 
00095   po::variables_map vm;
00096   po::store(po::parse_command_line(argc,argv,desc),vm);
00097   po::notify(vm);
00098 
00099   if (vm.count("help"))
00100   {
00101     cout<<desc<<"\n";
00102     return 1;
00103   }
00104 
00105   if (!vm.count("ndomains"))
00106   {
00107     cout << "ndomains must be specified !"<<endl;
00108     return 1;
00109   }
00110 
00111   ndomains = vm["ndomains"].as<int>();
00112   if (!vm.count("input-file") || !vm.count("output-file"))
00113   {
00114     cout << "input-file and output-file names must be specified"<<endl;
00115     return 1;
00116   }
00117 
00118 //   if (!vm.count("distributed") && !vm.count("meshname") )
00119 //   {
00120 //     cout << "MEDSPLITTER : for a serial MED file, mesh name must be selected with --meshname=..."<<endl;
00121 //     return 1;
00122 //   }
00123 
00124   input = vm["input-file"].as<string>();
00125   output = vm["output-file"].as<string>();
00126 
00127 //   if (vm.count("mesh-only"))
00128 //     mesh_only=true;
00129 
00130 //   if (vm.count("distributed"))
00131 //     is_sequential=false;
00132 
00133 //   if (is_sequential)
00134 //     meshname = vm["meshname"].as<string>();
00135 
00136   if (vm.count("plain-master"))
00137     xml_output_master=false;
00138 
00139   if (vm.count("creates-boundary-faces"))
00140     creates_boundary_faces=true;
00141 
00142   if (vm.count("split-families"))
00143     split_family=true;
00144 
00145   if (vm.count("empty-groups"))
00146     empty_groups=true;
00147 
00148   if (vm.count("dump-cpu-memory"))
00149     mesure_memory=true;
00150 
00151 #else // BOOST_PROGRAM_OPTIONS_LIB
00152 
00153   // Primitive parsing of command-line options
00154 
00155   string desc ("Available options:\n"
00156                "\t--help                  : produces this help message\n"
00157                //"\t--mesh-only            : do not create the fields contained in the original file(s)\n"
00158                //"\t--distributed          : specifies that the input file is distributed\n"
00159                "\t--input-file=<string>   : name of the input MED file\n"
00160                "\t--output-file=<string>  : name of the resulting file\n"
00161                //"\t--meshname=<string>    : name of the input mesh (not used with --distributed option)\n"
00162                "\t--ndomains=<number>     : number of subdomains in the output file, default is 1\n"
00163 #ifdef MED_ENABLE_PARMETIS
00164 #ifdef ENABLE_PTSCOTCH
00165                "\t--split-method=<string> : name of the splitting library (metis/scotch), default is metis\n"
00166 #endif
00167 #endif
00168                "\t--plain-master          : creates a plain masterfile instead of an XML file\n"
00169                "\t--creates-boundary-faces: creates the necessary faces so that faces joints are created in the output files\n"
00170                "\t--family-splitting      : preserves the family names instead of focusing on the groups\n"
00171                "\t--dump-cpu-memory       : dumps passed CPU time and maximal increase of used memory\n"
00172                );
00173 
00174   if (argc < 4) {
00175     cout << desc.c_str() << endl;
00176     return 1;
00177   }
00178 
00179   for (int i = 1; i < argc; i++) {
00180     if (strlen(argv[i]) < 3) {
00181       cout << desc.c_str() << endl;
00182       return 1;
00183     }
00184 
00185 /*    if (strncmp(argv[i],"--m",3) == 0) {
00186       if (strcmp(argv[i],"--mesh-only") == 0) {
00187         mesh_only = true;
00188         cout << "\tmesh-only = " << mesh_only << endl; // tmp
00189       }
00190       else if (strlen(argv[i]) > 11) { // "--meshname="
00191         meshname = (argv[i] + 11);
00192         cout << "\tmeshname = " << meshname << endl; // tmp
00193       }
00194     }
00195     else if (strncmp(argv[i],"--d",3) == 0) {
00196       is_sequential = false;
00197       cout << "\tis_sequential = " << is_sequential << endl; // tmp
00198     }
00199     else */if (strncmp(argv[i],"--i",3) == 0) {
00200       if (strlen(argv[i]) > 13) { // "--input-file="
00201         input = (argv[i] + 13);
00202         cout << "\tinput-file = " << input << endl; // tmp
00203       }
00204     }
00205     else if (strncmp(argv[i],"--o",3) == 0) {
00206       if (strlen(argv[i]) > 14) { // "--output-file="
00207         output = (argv[i] + 14);
00208         cout << "\toutput-file = " << output << endl; // tmp
00209       }
00210     }
00211     else if (strncmp(argv[i],"--s",3) == 0) {
00212       if (strlen(argv[i]) > 15) { // "--split-method="
00213         library = (argv[i] + 15);
00214         cout << "\tsplit-method = " << library << endl; // tmp
00215       }
00216     }
00217     else if (strncmp(argv[i],"--f",3) == 0) { //"--family-splitting"
00218       split_family=true;
00219       cout << "\tfamily-splitting true" << endl; // tmp
00220     }
00221     else if (strncmp(argv[i],"--n",3) == 0) {
00222       if (strlen(argv[i]) > 11) { // "--ndomains="
00223         ndomains = atoi(argv[i] + 11);
00224         cout << "\tndomains = " << ndomains << endl; // tmp
00225       }
00226     }
00227     else if (strncmp(argv[i],"--p",3) == 0) { // "--plain-master"
00228       xml_output_master = false;
00229       cout << "\txml_output_master = " << xml_output_master << endl; // tmp
00230     }
00231     else if (strncmp(argv[i],"--c",3) == 0) { // "--creates-boundary-faces"
00232       creates_boundary_faces = true;
00233       cout << "\tcreates_boundary_faces = " << creates_boundary_faces << endl; // tmp
00234     }
00235     else if (strncmp(argv[i],"--e",3) == 0) { // "--empty-groups"
00236       empty_groups = true;
00237       cout << "\tempty_groups = true" << endl; // tmp
00238     }
00239     else if (strncmp(argv[i],"--d",3) == 0) { // "--dump-cpu-memory"
00240       mesure_memory = true;
00241       cout << "\tdump-cpu-memory = true" << endl; // tmp
00242     }
00243     else {
00244       cout << desc.c_str() << endl;
00245       return 1;
00246     }
00247   }
00248 
00249 //   if (is_sequential && meshname.empty()) {
00250 //     cout << "Mesh name must be given for sequential(not distributed) input file." << endl;
00251 //     cout << desc << endl;
00252 //     return 1;
00253 //   }
00254 
00255 #endif // BOOST_PROGRAM_OPTIONS_LIB
00256 
00257 
00258   //testing whether it is possible to write a file at the specified location
00259   string outputtest = output + ".testioms.";
00260   ofstream testfile (outputtest.c_str());
00261   if (testfile.fail())
00262   { 
00263     cout << "MEDSPLITTER : output-file directory does not exist or is in read-only access" << endl;
00264     return 1;
00265   }
00266   //deletes test file
00267   remove(outputtest.c_str());
00268 
00269   // Beginning of the computation
00270 
00271   MPI_Init(&argc,&argv);
00272   
00273 
00274   // Loading the mesh collection
00275   cout << "MEDSPLITTER - reading input files "<<endl;
00276   MEDSPLITTER::ParaDomainSelector parallelizer(mesure_memory);
00277   MEDSPLITTER::MESHCollection collection(input,parallelizer);
00278 
00279   // Creating the graph and partitioning it   
00280   cout << "MEDSPLITTER - computing partition "<<endl;
00281 #ifdef MED_ENABLE_PARMETIS
00282 #ifndef ENABLE_PTSCOTCH
00283   library = "metis";
00284 #endif
00285 #else
00286   library = "scotch";
00287 #endif
00288   cout << "\tsplit-method = " << library << endl; // tmp
00289 
00290   auto_ptr< MEDSPLITTER::Topology > new_topo;
00291   if (library == "metis")
00292     new_topo.reset( collection.createPartition(ndomains,MEDSPLITTER::Graph::METIS));
00293   else
00294     new_topo.reset( collection.createPartition(ndomains,MEDSPLITTER::Graph::SCOTCH));
00295   parallelizer.evaluateMemory();
00296 
00297   // Creating a new mesh collection from the partitioning
00298   cout << "MEDSPLITTER - creating new meshes"<<endl;
00299   MEDSPLITTER::MESHCollection new_collection(collection,new_topo.get(),split_family,empty_groups);
00300   parallelizer.evaluateMemory();
00301 
00302   if (!xml_output_master)
00303     new_collection.setDriverType(MEDSPLITTER::MedAscii);
00304 
00305   new_collection.setSubdomainBoundaryCreates(creates_boundary_faces);
00306 
00307   cout << "MEDSPLITTER - writing output files "<<endl;
00308   new_collection.write(output);
00309 
00310   if ( mesure_memory )
00311     if ( parallelizer.isOnDifferentHosts() || parallelizer.rank()==0 )
00312     {
00313       MEDMEM::STRING text("proc ");
00314       text << parallelizer.rank() << ": elapsed time = " << parallelizer.getPassedTime()
00315            << ", max memory usage = " << parallelizer.evaluateMemory() << " KB";
00316       cout << text << endl;
00317     }
00318   // Casting the fields on the new collection
00319 //   if (!mesh_only)
00320 //     new_collection.castAllFields(*collection);
00321 
00322   MPI_Finalize();
00323 
00324   return 0;
00325 }