Back to index

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