1 // Copyright (C) 2007-2012 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // MED medsplitter : tool to split n MED files into p separate
21 // MED files with a partitioning specified
22 // by an external tool
23 // File : medsplitter.cxx
24 // Author : Vincent BERGEAUD (CEA-DEN/DANS/DM2S/SFME/LGLS)
27 #ifdef BOOST_PROGRAM_OPTIONS_LIB
28 #include <boost/program_options.hpp>
29 namespace po=boost::program_options;
35 #include "MEDMEM_define.hxx"
36 #include "MEDMEM_Mesh.hxx"
37 #include "MEDMEM_Family.hxx"
38 #include "MEDSPLITTER_Graph.hxx"
39 #include "MEDSPLITTER_MESHCollection.hxx"
40 #include "MEDSPLITTER_Topology.hxx"
46 int main(int argc, char** argv)
48 #ifndef MED_ENABLE_METIS
49 #ifndef MED_ENABLE_SCOTCH
50 cout << "Sorry, no one split method is available. Please, compile with METIS or SCOTCH."<<endl;
56 // by parsing the command line
57 bool mesh_only = false;
58 bool is_sequential = true;
59 bool xml_output_master=true;
60 bool creates_boundary_faces=false;
61 bool split_families=false;
62 bool empty_groups=false;
70 #ifdef BOOST_PROGRAM_OPTIONS_LIB
72 // Use boost::program_options for command-line options parsing
74 po::options_description desc("Available options");
76 ("help","produces this help message")
77 ("mesh-only","prevents the splitter from creating the fields contained in the original file(s)")
78 ("distributed","specifies that the input file is distributed")
79 ("input-file",po::value<string>(),"name of the input MED file")
80 ("output-file",po::value<string>(),"name of the resulting file")
81 ("meshname",po::value<string>(),"name of the input mesh")
82 #ifdef MED_ENABLE_METIS
83 #ifdef MED_ENABLE_SCOTCH
84 ("split-method",po::value<string>(&library)->default_value("metis"),"name of the splitting library (metis,scotch)")
87 ("ndomains",po::value<int>(&ndomains)->default_value(1),"number of subdomains in the output file")
88 ("plain-master","creates a plain masterfile instead of an XML file")
89 ("creates-boundary-faces","creates the necessary faces so that faces joints are created in the output files")
90 ("family-splitting","preserves the family names instead of focusing on the groups")
91 ("empty-groups","creates empty groups in zones that do not contain a group from the original domain");
94 po::store(po::parse_command_line(argc,argv,desc),vm);
103 if (!vm.count("ndomains"))
105 cout << "ndomains must be specified !"<<endl;
109 ndomains = vm["ndomains"].as<int>();
110 if (!vm.count("input-file") || !vm.count("output-file"))
112 cout << "input-file and output-file names must be specified"<<endl;
116 if (!vm.count("distributed") && !vm.count("meshname") )
118 cout << "MEDSPLITTER : for a serial MED file, mesh name must be selected with --meshname=..."<<endl;
122 input = vm["input-file"].as<string>();
123 output = vm["output-file"].as<string>();
125 if (vm.count("mesh-only"))
128 if (vm.count("distributed"))
132 meshname = vm["meshname"].as<string>();
134 if (vm.count("plain-master"))
135 xml_output_master=false;
137 if (vm.count("creates-boundary-faces"))
138 creates_boundary_faces=true;
140 if (vm.count("split-families"))
143 if (vm.count("empty-groups"))
146 #else // BOOST_PROGRAM_OPTIONS_LIB
148 // Primitive parsing of command-line options
150 string desc ("Available options:\n"
151 "\t--help : produces this help message\n"
152 "\t--mesh-only : do not create the fields contained in the original file(s)\n"
153 "\t--distributed : specifies that the input file is distributed\n"
154 "\t--input-file=<string> : name of the input MED file\n"
155 "\t--output-file=<string> : name of the resulting file\n"
156 "\t--meshname=<string> : name of the input mesh (not used with --distributed option)\n"
157 "\t--ndomains=<number> : number of subdomains in the output file, default is 1\n"
158 #ifdef MED_ENABLE_METIS
159 #ifdef MED_ENABLE_SCOTCH
160 "\t--split-method=<string>: name of the splitting library (metis/scotch), default is metis\n"
163 "\t--plain-master : creates a plain masterfile instead of an XML file\n"
164 "\t--creates-boundary-faces: creates the necessary faces so that faces joints are created in the output files\n"
165 "\t--family-splitting : preserves the family names instead of focusing on the groups\n"
166 "\t--empty-groups : creates empty groups in zones that do not contain a group from the original domain"
170 cout << desc.c_str() << endl;
174 for (int i = 1; i < argc; i++) {
175 if (strlen(argv[i]) < 3) {
176 cout << desc.c_str() << endl;
180 if (strncmp(argv[i],"--m",3) == 0) {
181 if (strcmp(argv[i],"--mesh-only") == 0) {
183 cout << "\tmesh-only = " << mesh_only << endl; // tmp
185 else if (strlen(argv[i]) > 11) { // "--meshname="
186 meshname = (argv[i] + 11);
187 cout << "\tmeshname = " << meshname << endl; // tmp
190 else if (strncmp(argv[i],"--d",3) == 0) {
191 is_sequential = false;
192 cout << "\tis_sequential = " << is_sequential << endl; // tmp
194 else if (strncmp(argv[i],"--i",3) == 0) {
195 if (strlen(argv[i]) > 13) { // "--input-file="
196 input = (argv[i] + 13);
197 cout << "\tinput-file = " << input << endl; // tmp
200 else if (strncmp(argv[i],"--o",3) == 0) {
201 if (strlen(argv[i]) > 14) { // "--output-file="
202 output = (argv[i] + 14);
203 cout << "\toutput-file = " << output << endl; // tmp
206 else if (strncmp(argv[i],"--s",3) == 0) {
207 if (strlen(argv[i]) > 15) { // "--split-method="
208 library = (argv[i] + 15);
209 cout << "\tsplit-method = " << library << endl; // tmp
212 else if (strncmp(argv[i],"--f",3) == 0) { //"--family-splitting"
214 cout << "\tfamily-splitting true" << endl; // tmp
216 else if (strncmp(argv[i],"--n",3) == 0) {
217 if (strlen(argv[i]) > 11) { // "--ndomains="
218 ndomains = atoi(argv[i] + 11);
219 cout << "\tndomains = " << ndomains << endl; // tmp
222 else if (strncmp(argv[i],"--p",3) == 0) { // "--plain-master"
223 xml_output_master = false;
224 cout << "\txml_output_master = " << xml_output_master << endl; // tmp
226 else if (strncmp(argv[i],"--c",3) == 0) { // "--creates-boundary-faces"
227 creates_boundary_faces = true;
228 cout << "\tcreates_boundary_faces = " << creates_boundary_faces << endl; // tmp
230 else if (strncmp(argv[i],"--e",3) == 0) { // "--empty-groups"
232 cout << "\tempty_groups = true" << endl; // tmp
235 cout << desc.c_str() << endl;
240 if (is_sequential && meshname.empty()) {
241 cout << "Mesh name must be given for sequential(not distributed) input file." << endl;
242 cout << desc << endl;
246 #endif // BOOST_PROGRAM_OPTIONS_LIB
249 //testing whether it is possible to write a file at the specified location
250 string outputtest = output + ".testioms.";
251 ofstream testfile (outputtest.c_str());
254 cout << "MEDSPLITTER : output-file directory does not exist or is in read-only access" << endl;
258 remove(outputtest.c_str());
260 // Beginning of the computation
262 // Loading the mesh collection
263 MEDSPLITTER::MESHCollection* collection;
264 cout << "MEDSPLITTER - reading input files "<<endl;
266 collection = new MEDSPLITTER::MESHCollection(input,meshname);
268 collection = new MEDSPLITTER::MESHCollection(input);
270 cout << "MEDSPLITTER - computing partition "<<endl;
272 // Creating the graph and partitioning it
273 #ifdef MED_ENABLE_METIS
274 if ( library.empty() )
277 #ifdef MED_ENABLE_SCOTCH
278 if ( library.empty() )
282 cout << "\tsplit-method = " << library << endl; // tmp
284 MEDSPLITTER::Topology* new_topo;
285 if (library == "metis")
286 new_topo = collection->createPartition(ndomains,MEDSPLITTER::Graph::METIS);
288 new_topo = collection->createPartition(ndomains,MEDSPLITTER::Graph::SCOTCH);
290 cout << "MEDSPLITTER - creating new meshes"<<endl;
292 // Creating a new mesh collection from the partitioning
293 MEDSPLITTER::MESHCollection new_collection(*collection, new_topo, split_families, empty_groups);
300 if (!xml_output_master)
301 new_collection.setDriverType(MEDSPLITTER::MedAscii);
303 new_collection.setSubdomainBoundaryCreates(creates_boundary_faces);
305 cout << "MEDSPLITTER - writing output files "<<endl;
306 new_collection.write(output);
308 // Casting the fields on the new collection
310 new_collection.castAllFields(*collection);