--- /dev/null
+// Copyright (C) 2007-2010 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+#include <vector>
+#include <string>
+#include <map>
+#include <set>
+
+#include <iostream>
+#include <fstream>
+
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#include <sys/time.h>
+//Debug macros
+#include "MEDMEM_Utilities.hxx"
+#include "MEDMEM_Exception.hxx"
+//MEDMEM includes
+// #include "MEDMEM_DriversDef.hxx"
+// #include "MEDMEM_Mesh.hxx"
+// #include "MEDMEM_Med.hxx"
+// #include "MEDMEM_Field.hxx"
+// #include "MEDMEM_Meshing.hxx"
+// #include "MEDMEM_CellModel.hxx"
+// #include "MEDMEM_SkyLineArray.hxx"
+// #include "MEDMEM_ConnectZone.hxx"
+#include "MEDCouplingUMesh.hxx"
+#include "MEDLoader.hxx"
+
+//MEDPARTITIONER includes
+#include "MEDPARTITIONER_Topology.hxx"
+#include "MEDPARTITIONER_ParallelTopology.hxx"
+#include "MEDPARTITIONER_SequentialTopology.hxx"
+#include "MEDPARTITIONER_MESHCollectionDriver.hxx"
+#include "MEDPARTITIONER_MESHCollection.hxx"
+#include "MEDPARTITIONER_MESHCollectionMedAsciiDriver.hxx"
+#include "MEDPARTITIONER_ParaDomainSelector.hxx"
+
+using namespace MEDPARTITIONER;
+
+//template inclusion
+//#include "MEDPARTITIONER_MESHCollectionMedAsciiDriver.H"
+
+
+MESHCollectionMedAsciiDriver::MESHCollectionMedAsciiDriver(MESHCollection* collection):MESHCollectionDriver(collection)
+{
+}
+
+/*!reads a MED File v>=2.3
+ * and mounts the corresponding meshes in memory
+ * the connect zones are created from the joints
+ *
+ *\param filename ascii file containing the list of MED v2.3 files
+ * */
+
+int MESHCollectionMedAsciiDriver::read(const char* filename, ParaDomainSelector* domainSelector)
+{
+
+ const char* LOC = "MEDPARTITIONER::MESHCollectionDriver::read()";
+ BEGIN_OF_MED(LOC);
+
+ //ditributed meshes
+ vector<int*> cellglobal;
+ vector<int*> nodeglobal;
+ vector<int*> faceglobal;
+
+ int nbdomain;
+
+ // reading ascii master file
+ try{
+ MESSAGE_MED("Start reading");
+ ifstream asciiinput(filename);
+
+ if (!asciiinput)
+ throw MEDMEM::MEDEXCEPTION("MEDPARTITIONER read - Master File does not exist");
+
+ char charbuffer[512];
+ asciiinput.getline(charbuffer,512);
+
+ while (charbuffer[0]=='#')
+ {
+ asciiinput.getline(charbuffer,512);
+ }
+
+ //reading number of domains
+ nbdomain=atoi(charbuffer);
+ cout << "nb domain "<<nbdomain<<endl;
+ // asciiinput>>nbdomain;
+ _filename.resize(nbdomain);
+ _meshname.resize(nbdomain);
+ (_collection->getMesh()).resize(nbdomain);
+ cellglobal.resize(nbdomain);
+ nodeglobal.resize(nbdomain);
+ faceglobal.resize(nbdomain);
+
+ if (nbdomain == 0)
+ throw MEDMEM::MEDEXCEPTION("Empty ASCII master file");
+ for (int i=0; i<nbdomain;i++)
+ {
+
+ //reading information about the domain
+ string mesh;
+ int idomain;
+ string host;
+ cellglobal[i]=0;
+ faceglobal[i]=0;
+ nodeglobal[i]=0;
+
+ asciiinput >> mesh >> idomain >> _meshname[i] >> host >> _filename[i];
+
+ //Setting the name of the global mesh (which is the same
+ //for all the subdomains)
+ if (i==0)
+ _collection->setName(mesh);
+
+ if (idomain!=i+1)
+ {
+ cerr<<"Error : domain must be written from 1 to N in asciifile descriptor"<<endl;
+ return 1;
+ }
+ if ( !domainSelector || domainSelector->isMyDomain(i))
+ readSubdomain(cellglobal,faceglobal,nodeglobal, i);
+
+ }//loop on domains
+ MESSAGE_MED("end of read");
+ }//of try
+ catch(...)
+ {
+ cerr << "I/O error reading parallel MED file"<<endl;
+ throw;
+ }
+
+ //creation of topology from mesh and connect zones
+ ParallelTopology* aPT = new ParallelTopology
+ ((_collection->getMesh()), (_collection->getCZ()), cellglobal, nodeglobal, faceglobal);
+ _collection->setTopology(aPT);
+
+ for (int i=0; i<nbdomain; i++)
+ {
+ if (cellglobal[i]!=0) delete[] cellglobal[i];
+ if (nodeglobal[i]!=0) delete[] nodeglobal[i];
+ if (faceglobal[i]!=0) delete[] faceglobal[i];
+ }
+
+ END_OF_MED(LOC);
+ return 0;
+}
+
+
+/*! writes the collection of meshes in a
+ * MED v2.3 file
+ * with the connect zones being written as joints
+ * \param filename name of the ascii file containing the meshes description
+ */
+void MESHCollectionMedAsciiDriver::write(const char* filename, ParaDomainSelector* domainSelector)
+{
+
+ const char* LOC = "MEDPARTITIONER::MESHCollectionDriver::write()";
+ BEGIN_OF_MED(LOC);
+
+ int nbdomains= _collection->getMesh().size();
+ _filename.resize(nbdomains);
+
+ //loop on the domains
+ for (int idomain=0; idomain<nbdomains;idomain++)
+ {
+ string distfilename;
+
+ ostringstream suffix;
+ suffix << filename<< idomain+1 <<".med";
+
+ distfilename=suffix.str();
+
+ _filename[idomain]=distfilename;
+
+ MESSAGE_MED("File name "<<distfilename);
+
+ if ( !domainSelector || domainSelector->isMyDomain( idomain ) )
+ {
+ if ( !_collection->getMesh()[idomain]->getNumberOfCells()==0 ) continue;//empty domain
+
+ MEDLoader::WriteUMesh(distfilename.c_str(),(_collection->getMesh())[idomain],true);
+
+ // writeSubdomain(idomain, nbdomains, distfilename.c_str(), domainSelector);
+ }
+ }
+
+ // write master file
+ if ( !domainSelector || domainSelector->rank() == 0 )
+ {
+ ofstream file(filename);
+
+ file <<"#MED Fichier V 2.3"<<" "<<endl;
+ file <<"#"<<" "<<endl;
+ file<<_collection->getMesh().size()<<" "<<endl;
+
+ for (int idomain=0; idomain<nbdomains;idomain++)
+ file << _collection->getName() <<" "<< idomain+1 << " "
+ << (_collection->getMesh())[idomain]->getName() << " localhost "
+ << _filename[idomain] << " "<<endl;
+ }
+
+ END_OF_MED(LOC);
+
+}
--- /dev/null
+// Copyright (C) 2007-2010 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+#include <vector>
+#include <string>
+#include <map>
+#include <set>
+#include <cstring>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#include <sys/time.h>
+
+#include "MEDMEM_Utilities.hxx"
+#include "MEDMEM_Exception.hxx"
+//MEDSPLITTER includes
+#include "MEDCouplingUMesh.hxx"
+#include "MEDLoader.hxx"
+#include "MEDFileMesh.hxx"
+#include "MEDPARTITIONER_Topology.hxx"
+#include "MEDPARTITIONER_ParallelTopology.hxx"
+#include "MEDPARTITIONER_SequentialTopology.hxx"
+#include "MEDPARTITIONER_MESHCollectionDriver.hxx"
+#include "MEDPARTITIONER_MESHCollection.hxx"
+#include "MEDPARTITIONER_MESHCollectionMedXMLDriver.hxx"
+#include "MEDPARTITIONER_ParaDomainSelector.hxx"
+
+using namespace MEDPARTITIONER;
+
+//template inclusion
+//#include "MEDPARTITIONER_MESHCollectionMedXMLDriver.H"
+
+/*!\class MESHCollectionMedXMLDriver
+ *
+ *\brief Driver for MED 3.2 files having XML master files
+ *
+ * Driver for reading and writing distributed files
+ * for which the master file is written in an XML format compliant with
+ * the MED 3.2 specification.
+ * The reading and writing of the meshes and fields are apart :
+ * the meshes must always be written/read before the fields. Reading/Writing fields
+ * is optional and is done field after field. API for reading/writing fields
+ * is written with a template so that MEDMEM::FIELD<int> and MEDMEM::FIELD<double>
+ * can be conveniently handled.
+*/
+
+MESHCollectionMedXMLDriver::MESHCollectionMedXMLDriver(MESHCollection* collection):MESHCollectionDriver(collection)
+{
+}
+
+/*!reads a MED File XML Master File v>=2.3
+ * and mounts the corresponding meshes in memory
+ * the connect zones are created from the joints
+ *
+ *\param filename XML file containing the list of MED v2.3 files
+ * */
+
+int MESHCollectionMedXMLDriver::read(const char* filename, ParaDomainSelector* domainSelector)
+{
+
+ const char* LOC = "MEDPARTITIONER::MESHCollectionDriver::read()";
+ BEGIN_OF_MED(LOC);
+
+ //ditributed meshes
+ vector<int*> cellglobal;
+ vector<int*> nodeglobal;
+ vector<int*> faceglobal;
+
+ int nbdomain;
+
+ _master_filename=filename;
+
+ // reading ascii master file
+ try{
+ MESSAGE_MED("Start reading");
+
+ // Setting up the XML tree corresponding to filename
+ xmlDocPtr master_doc=xmlParseFile(filename);
+
+ if (!master_doc)
+ throw MEDMEM::MEDEXCEPTION("MEDPARTITIONER XML read - Master File does not exist o r is not compliant with XML scheme");
+
+ ////////////////////
+ //number of domains
+ ////////////////////
+ xmlXPathContextPtr xpathCtx = xmlXPathNewContext(master_doc);
+ xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression(BAD_CAST "//splitting/subdomain", xpathCtx);
+ if (xpathObj==0 || xpathObj->nodesetval->nodeNr ==0)
+ throw MEDMEM::MEDEXCEPTION("MEDPARTITIONER read - XML Master File does not contain /MED/splitting/subdomain node");
+
+ /* as subdomain has only one property which is "number"
+ * it suffices to take the content of its first child */
+ const char* mystring = (const char*)xpathObj->nodesetval->nodeTab[0]->properties->children->content;
+ sscanf(mystring, "%d", &nbdomain);
+
+ //////////////////
+ //mesh name
+ //////////////////
+ xpathObj = xmlXPathEvalExpression(BAD_CAST "//content/mesh", xpathCtx);
+ if (xpathObj==0 || xpathObj->nodesetval->nodeNr ==0)
+ throw MEDMEM::MEDEXCEPTION("MEDPARTITIONER read - XML Master File does not contain /MED/content/mesh node");
+ _collection->setName( (const char*)xpathObj->nodesetval->nodeTab[0]->properties->children->content);
+
+ cout << "nb domain " << nbdomain << endl;
+ _filename.resize(nbdomain);
+ _meshname.resize(nbdomain);
+ (_collection->getMesh()).resize(nbdomain);
+ (_collection->getFaceMesh()).resize(nbdomain);
+ (_collection->getCellFamilyIds()).resize(nbdomain);
+ (_collection->getFaceFamilyIds()).resize(nbdomain);
+
+ cellglobal.resize(nbdomain);
+ nodeglobal.resize(nbdomain);
+ faceglobal.resize(nbdomain);
+
+
+ // retrieving the node which contains the file names
+ const char filechar[]="//files/subfile";
+ xpathObj = xmlXPathEvalExpression(BAD_CAST filechar, xpathCtx);
+ if (xpathObj==0 || xpathObj->nodesetval->nodeNr ==0)
+ throw MEDMEM::MEDEXCEPTION("MEDPARTITIONER read - XML Master File does not contain /MED/files/subfile nodes");
+ int nbfiles = xpathObj->nodesetval ->nodeNr;
+
+ for (int i=0; i<nbfiles;i++)
+ {
+ //reading information about the domain
+
+ string host;
+
+ cellglobal[i]=0;
+ faceglobal[i]=0;
+ nodeglobal[i]=0;
+
+ ////////////////////////////
+ //reading file names
+ ////////////////////////////
+ std::ostringstream name_search_string;
+ name_search_string<<"//files/subfile[@id=\""<<i+1<<"\"]/name";
+ //cout <<name_search_string.str()<<endl;
+ xmlXPathObjectPtr xpathObjfilename =
+ xmlXPathEvalExpression(BAD_CAST name_search_string.str().c_str(),xpathCtx);
+ if (xpathObjfilename->nodesetval ==0)
+ throw MEDMEM::MEDEXCEPTION("MED XML reader : Error retrieving file name ");
+ _filename[i]=(const char*)xpathObjfilename->nodesetval->nodeTab[0]->children->content;
+
+ ////////////////////////////////
+ //reading the local mesh names
+ ////////////////////////////////
+ ostringstream mesh_search_string;
+ mesh_search_string<<"//mapping/mesh/chunk[@subdomain=\""<<i+1<<"\"]/name";
+
+ xmlXPathObjectPtr xpathMeshObj = xmlXPathEvalExpression(BAD_CAST mesh_search_string.str().c_str(),xpathCtx);
+ if (xpathMeshObj->nodesetval ==0)
+ throw MEDMEM::MEDEXCEPTION("MED XML reader : Error retrieving mesh name ");
+ _meshname[i]=(const char*)xpathMeshObj->nodesetval->nodeTab[0]->children->content;
+
+ if ( !domainSelector || domainSelector->isMyDomain(i))
+ readSubdomain(cellglobal, faceglobal, nodeglobal, i);
+ xmlXPathFreeObject(xpathObjfilename);
+
+ xmlXPathFreeObject(xpathMeshObj);
+ }//loop on domains
+
+ // LIBXML cleanup
+ xmlXPathFreeObject(xpathObj);
+ xmlXPathFreeContext(xpathCtx);
+ xmlFreeDoc(master_doc);
+
+ MESSAGE_MED("end of read");
+ }//of try
+ catch(...)
+ {
+ throw MEDMEM::MEDEXCEPTION("I/O error reading parallel MED file");
+ }
+
+ //creation of topology from mesh and connect zones
+ ParallelTopology* aPT = new ParallelTopology
+ ((_collection->getMesh()), (_collection->getCZ()), cellglobal, nodeglobal, faceglobal);
+ _collection->setTopology(aPT);
+ _collection->setDomainNames(_collection->getName());
+ for (int i=0; i<nbdomain; i++)
+ {
+ if (cellglobal[i]!=0) delete[] cellglobal[i];
+ if (nodeglobal[i]!=0) delete[] nodeglobal[i];
+ if (faceglobal[i]!=0) delete[] faceglobal[i];
+ }
+
+ END_OF_MED(LOC);
+ return 0;
+}
+
+
+/*! writes the collection of meshes in a
+ * MED v2.3 XML file
+ * with the connect zones being written as joints
+ * \param filename name of the XML file containing the meshes description
+ */
+void MESHCollectionMedXMLDriver::write(const char* filename, ParaDomainSelector* domainSelector)
+{
+
+ const char* LOC = "MEDPARTITIONER::MESHCollectionDriver::writeXML()";
+ BEGIN_OF_MED(LOC);
+
+ xmlDocPtr master_doc = 0;
+ xmlNodePtr root_node = 0, node, node2;
+ // xmlDTDPtr dtd = 0;
+
+ char buff[256];
+
+ //Creating the XML document
+
+ master_doc = xmlNewDoc(BAD_CAST "1.0");
+ root_node = xmlNewNode(0, BAD_CAST "root");
+ xmlDocSetRootElement(master_doc,root_node);
+
+ //Creating child nodes
+
+ // Version tag
+ node = xmlNewChild(root_node, 0, BAD_CAST "version",0);
+ xmlNewProp(node, BAD_CAST "maj", BAD_CAST "2");
+ xmlNewProp(node, BAD_CAST "min", BAD_CAST "3");
+ xmlNewProp(node, BAD_CAST "ver", BAD_CAST "1");
+
+ //Description tag
+
+ time_t present;
+ time( &present);
+ struct tm *time_asc = localtime(&present);
+ char date[6];
+ sprintf(date,"%02d%02d%02d",time_asc->tm_year
+ ,time_asc->tm_mon+1
+ ,time_asc->tm_mday);
+
+ node = xmlNewChild(root_node,0, BAD_CAST "description",0);
+
+ xmlNewProp(node, BAD_CAST "what", BAD_CAST _collection->getDescription().c_str());
+ xmlNewProp(node, BAD_CAST "when", BAD_CAST date);
+
+ //Content tag
+ node =xmlNewChild(root_node,0, BAD_CAST "content",0);
+ node2 = xmlNewChild(node, 0, BAD_CAST "mesh",0);
+ xmlNewProp(node2, BAD_CAST "name", BAD_CAST _collection->getName().c_str());
+
+ //Splitting tag
+ node=xmlNewChild(root_node,0,BAD_CAST "splitting",0);
+ node2=xmlNewChild(node,0,BAD_CAST "subdomain",0);
+ sprintf(buff, "%d", _collection->getMesh().size());
+ xmlNewProp(node2, BAD_CAST "number", BAD_CAST buff);
+ node2=xmlNewChild(node,0,BAD_CAST "global_numbering",0);
+ xmlNewProp(node2, BAD_CAST "present", BAD_CAST "yes");
+
+ //Files tag
+ xmlNodePtr file_node=xmlNewChild(root_node,0,BAD_CAST "files",0);
+
+ //Mapping tag
+ node = xmlNewChild(root_node,0,BAD_CAST "mapping",0);
+ xmlNodePtr mesh_node = xmlNewChild(node, 0, BAD_CAST "mesh",0);
+ xmlNewProp(mesh_node, BAD_CAST "name", BAD_CAST _collection->getName().c_str());
+
+ int nbdomains= _collection->getMesh().size();
+ _filename.resize(nbdomains);
+
+ //loop on the domains
+ for (int idomain=nbdomains-1; idomain>=0;idomain--)
+ {
+ string distfilename;
+
+ ostringstream suffix;
+ suffix << filename<< idomain+1 <<".med";
+
+ distfilename=suffix.str();
+
+ _filename[idomain]=distfilename;
+
+ MESSAGE_MED("File name "<<distfilename);
+ if ( !domainSelector || domainSelector->isMyDomain( idomain ) )
+ {
+ if ( (_collection->getMesh())[idomain]->getNumberOfCells()==0 ) continue;//empty domain
+ writeMedFile(idomain,distfilename);
+
+ //updating the ascii description file
+ node = xmlNewChild(file_node, 0, BAD_CAST "subfile",0);
+ sprintf (buff,"%d",idomain+1);
+ xmlNewProp(node, BAD_CAST "id", BAD_CAST buff);
+ xmlNewChild(node,0,BAD_CAST "name",BAD_CAST distfilename.c_str());
+ xmlNewChild(node,0,BAD_CAST "machine",BAD_CAST "localhost");
+
+ node = xmlNewChild(mesh_node,0, BAD_CAST "chunk",0);
+ xmlNewProp(node, BAD_CAST "subdomain", BAD_CAST buff);
+ xmlNewChild(node,0,BAD_CAST "name", BAD_CAST (_collection->getMesh())[idomain]->getName());
+ }
+ }
+ string myfile(filename);
+ myfile.append(".xml");
+ _master_filename=myfile;
+ if ( !domainSelector || domainSelector->rank() == 0 )
+ xmlSaveFormatFileEnc(myfile.c_str(), master_doc, "UTF-8", 1);
+ xmlFreeDoc(master_doc);
+ xmlCleanupParser();
+
+ END_OF_MED(LOC);
+
+}
--- /dev/null
+// Copyright (C) 2007-2010 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// MED medsplitter : tool to split n MED files into p separate
+// MED files with a partitioning specified
+// by an external tool
+// File : medsplitter.cxx
+// Author : Vincent BERGEAUD (CEA-DEN/DANS/DM2S/SFME/LGLS)
+// Module : MED
+//
+#ifdef BOOST_PROGRAM_OPTIONS_LIB
+#include <boost/program_options.hpp>
+namespace po=boost::program_options;
+#endif
+
+#include <string>
+#include <fstream>
+
+#include "MEDMEM_define.hxx"
+#include "MEDMEM_Mesh.hxx"
+#include "MEDMEM_Family.hxx"
+#include "MEDPARTITIONER_Graph.hxx"
+#include "MEDPARTITIONER_MESHCollection.hxx"
+#include "MEDPARTITIONER_Topology.hxx"
+
+using namespace std;
+
+
+
+int main(int argc, char** argv)
+{
+#ifndef ENABLE_METIS
+#ifndef ENABLE_SCOTCH
+ cout << "Sorry, no one split method is available. Please, compile with METIS or SCOTCH."<<endl;
+ return 1;
+#endif
+#endif
+
+ // Defining options
+ // by parsing the command line
+ bool mesh_only = false;
+ bool is_sequential = true;
+ bool xml_output_master=true;
+ bool creates_boundary_faces=false;
+ bool split_families=false;
+ bool empty_groups=false;
+
+ string input;
+ string output;
+ string meshname;
+ string library;
+ int ndomains;
+
+#ifdef BOOST_PROGRAM_OPTIONS_LIB
+
+ // Use boost::program_options for command-line options parsing
+
+ po::options_description desc("Available options");
+ desc.add_options()
+ ("help","produces this help message")
+ ("mesh-only","prevents the splitter from creating the fields contained in the original file(s)")
+ ("distributed","specifies that the input file is distributed")
+ ("input-file",po::value<string>(),"name of the input MED file")
+ ("output-file",po::value<string>(),"name of the resulting file")
+ ("meshname",po::value<string>(),"name of the input mesh")
+#ifdef ENABLE_METIS
+#ifdef ENABLE_SCOTCH
+ ("split-method",po::value<string>(&library)->default_value("metis"),"name of the splitting library (metis,scotch)")
+#endif
+#endif
+ ("ndomains",po::value<int>(&ndomains)->default_value(1),"number of subdomains in the output file")
+ ("plain-master","creates a plain masterfile instead of an XML file")
+ ("creates-boundary-faces","creates the necessary faces so that faces joints are created in the output files")
+ ("family-splitting","preserves the family names instead of focusing on the groups")
+ ("empty-groups","creates empty groups in zones that do not contain a group from the original domain");
+
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc,argv,desc),vm);
+ po::notify(vm);
+
+ if (vm.count("help"))
+ {
+ cout<<desc<<"\n";
+ return 1;
+ }
+
+ if (!vm.count("ndomains"))
+ {
+ cout << "ndomains must be specified !"<<endl;
+ return 1;
+ }
+
+ ndomains = vm["ndomains"].as<int>();
+ if (!vm.count("input-file") || !vm.count("output-file"))
+ {
+ cout << "input-file and output-file names must be specified"<<endl;
+ return 1;
+ }
+
+ if (!vm.count("distributed") && !vm.count("meshname") )
+ {
+ cout << "MEDPARTITIONER : for a serial MED file, mesh name must be selected with --meshname=..."<<endl;
+ return 1;
+ }
+
+ input = vm["input-file"].as<string>();
+ output = vm["output-file"].as<string>();
+
+ if (vm.count("mesh-only"))
+ mesh_only=true;
+
+ if (vm.count("distributed"))
+ is_sequential=false;
+
+ if (is_sequential)
+ meshname = vm["meshname"].as<string>();
+
+ if (vm.count("plain-master"))
+ xml_output_master=false;
+
+ if (vm.count("creates-boundary-faces"))
+ creates_boundary_faces=true;
+
+ if (vm.count("split-families"))
+ split_families=true;
+
+ if (vm.count("empty-groups"))
+ empty_groups=true;
+
+#else // BOOST_PROGRAM_OPTIONS_LIB
+
+ // Primitive parsing of command-line options
+
+ string desc ("Available options:\n"
+ "\t--help : produces this help message\n"
+ "\t--mesh-only : do not create the fields contained in the original file(s)\n"
+ "\t--distributed : specifies that the input file is distributed\n"
+ "\t--input-file=<string> : name of the input MED file\n"
+ "\t--output-file=<string> : name of the resulting file\n"
+ "\t--meshname=<string> : name of the input mesh (not used with --distributed option)\n"
+ "\t--ndomains=<number> : number of subdomains in the output file, default is 1\n"
+#ifdef ENABLE_METIS
+#ifdef ENABLE_SCOTCH
+ "\t--split-method=<string>: name of the splitting library (metis/scotch), default is metis\n"
+#endif
+#endif
+ "\t--plain-master : creates a plain masterfile instead of an XML file\n"
+ "\t--creates-boundary-faces: creates the necessary faces so that faces joints are created in the output files\n"
+ "\t--family-splitting : preserves the family names instead of focusing on the groups\n"
+ "\t--empty-groups : creates empty groups in zones that do not contain a group from the original domain"
+ );
+
+ if (argc < 4) {
+ cout << desc.c_str() << endl;
+ return 1;
+ }
+
+ for (int i = 1; i < argc; i++) {
+ if (strlen(argv[i]) < 3) {
+ cout << desc.c_str() << endl;
+ return 1;
+ }
+
+ if (strncmp(argv[i],"--m",3) == 0) {
+ if (strcmp(argv[i],"--mesh-only") == 0) {
+ mesh_only = true;
+ cout << "\tmesh-only = " << mesh_only << endl; // tmp
+ }
+ else if (strlen(argv[i]) > 11) { // "--meshname="
+ meshname = (argv[i] + 11);
+ cout << "\tmeshname = " << meshname << endl; // tmp
+ }
+ }
+ else if (strncmp(argv[i],"--d",3) == 0) {
+ is_sequential = false;
+ cout << "\tis_sequential = " << is_sequential << endl; // tmp
+ }
+ else if (strncmp(argv[i],"--i",3) == 0) {
+ if (strlen(argv[i]) > 13) { // "--input-file="
+ input = (argv[i] + 13);
+ cout << "\tinput-file = " << input << endl; // tmp
+ }
+ }
+ else if (strncmp(argv[i],"--o",3) == 0) {
+ if (strlen(argv[i]) > 14) { // "--output-file="
+ output = (argv[i] + 14);
+ cout << "\toutput-file = " << output << endl; // tmp
+ }
+ }
+ else if (strncmp(argv[i],"--s",3) == 0) {
+ if (strlen(argv[i]) > 15) { // "--split-method="
+ library = (argv[i] + 15);
+ cout << "\tsplit-method = " << library << endl; // tmp
+ }
+ }
+ else if (strncmp(argv[i],"--f",3) == 0) { //"--family-splitting"
+ split_families=true;
+ cout << "\tfamily-splitting true" << endl; // tmp
+ }
+ else if (strncmp(argv[i],"--n",3) == 0) {
+ if (strlen(argv[i]) > 11) { // "--ndomains="
+ ndomains = atoi(argv[i] + 11);
+ cout << "\tndomains = " << ndomains << endl; // tmp
+ }
+ }
+ else if (strncmp(argv[i],"--p",3) == 0) { // "--plain-master"
+ xml_output_master = false;
+ cout << "\txml_output_master = " << xml_output_master << endl; // tmp
+ }
+ else if (strncmp(argv[i],"--c",3) == 0) { // "--creates-boundary-faces"
+ creates_boundary_faces = true;
+ cout << "\tcreates_boundary_faces = " << creates_boundary_faces << endl; // tmp
+ }
+ else if (strncmp(argv[i],"--e",3) == 0) { // "--empty-groups"
+ empty_groups = true;
+ cout << "\tempty_groups = true" << endl; // tmp
+ }
+ else {
+ cout << desc.c_str() << endl;
+ return 1;
+ }
+ }
+
+ if (is_sequential && meshname.empty()) {
+ cout << "Mesh name must be given for sequential(not distributed) input file." << endl;
+ cout << desc << endl;
+ return 1;
+ }
+
+#endif // BOOST_PROGRAM_OPTIONS_LIB
+
+
+ //testing whether it is possible to write a file at the specified location
+ string outputtest = output + ".testioms.";
+ ofstream testfile (outputtest.c_str());
+ if (testfile.fail())
+ {
+ cout << "MEDPARTITIONER : output-file directory does not exist or is in read-only access" << endl;
+ return 1;
+ };
+ //deletes test file
+ remove(outputtest.c_str());
+
+ // Beginning of the computation
+
+ // Loading the mesh collection
+ MEDPARTITIONER::MESHCollection* collection;
+ cout << "MEDPARTITIONER - reading input files "<<endl;
+ if (is_sequential)
+ collection = new MEDPARTITIONER::MESHCollection(input,meshname);
+ else
+ collection = new MEDPARTITIONER::MESHCollection(input);
+
+ cout << "MEDPARTITIONER - computing partition "<<endl;
+
+ // Creating the graph and partitioning it
+#ifdef ENABLE_METIS
+#ifndef ENABLE_SCOTCH
+ library = "metis";
+#endif
+#else
+ library = "scotch";
+#endif
+ cout << "\tsplit-method = " << library << endl; // tmp
+
+ MEDPARTITIONER::Topology* new_topo;
+ if (library == "metis")
+ new_topo = collection->createPartition(ndomains,MEDPARTITIONER::Graph::METIS);
+ else
+ new_topo = collection->createPartition(ndomains,MEDPARTITIONER::Graph::SCOTCH);
+
+ cout << "MEDPARTITIONER - creating new meshes"<<endl;
+
+ // Creating a new mesh collection from the partitioning
+ MEDPARTITIONER::MESHCollection new_collection(*collection, new_topo, split_families, empty_groups);
+ if (mesh_only)
+ {
+ delete collection;
+ collection=0;
+ }
+
+ if (!xml_output_master)
+ new_collection.setDriverType(MEDPARTITIONER::MedAscii);
+
+ // new_collection.setSubdomainBoundaryCreates(creates_boundary_faces);
+
+ cout << "MEDPARTITIONER - writing output files "<<endl;
+ new_collection.write(output);
+
+ // Casting the fields on the new collection
+// if (!mesh_only)
+// new_collection.castAllFields(*collection);
+
+
+ // Cleaning memory
+ delete collection;
+ delete new_topo;
+
+ return 0;
+}
--- /dev/null
+// Copyright (C) 2007-2010 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// MED medsplitter : tool to split n MED files into p separate
+// MED files with a partitioning specified
+// by an external tool
+// File : medsplitter.cxx
+// Module : MED
+//
+
+#include "MEDPARTITIONER_MESHCollection.hxx"
+#include "MEDPARTITIONER_Topology.hxx"
+#include "MEDPARTITIONER_ParaDomainSelector.hxx"
+
+#include "MEDMEM_STRING.hxx"
+#include <cstdlib>
+
+#ifdef HAVE_MPI2
+#include <mpi.h>
+#endif
+
+#include <fstream>
+
+#ifdef BOOST_PROGRAM_OPTIONS_LIB
+#include <boost/program_options.hpp>
+namespace po=boost::program_options;
+#endif
+
+using namespace std;
+
+
+
+int main(int argc, char** argv)
+{
+#ifndef ENABLE_PARMETIS
+#ifndef ENABLE_PTSCOTCH
+ cout << "Sorry, no one split method is available. Please, compile with ParMETIS or PT-SCOTCH."<<endl;
+ return 1;
+#endif
+#endif
+
+ // Defining options
+ // by parsing the command line
+ //bool mesh_only = false;
+ //bool is_sequential = true;
+ bool xml_output_master=true;
+ bool creates_boundary_faces=false;
+ bool split_family=false;
+ bool empty_groups=false;
+ bool mesure_memory=false;
+
+ string input;
+ string output;
+ string meshname;
+ string library;
+ int ndomains;
+
+#ifdef BOOST_PROGRAM_OPTIONS_LIB
+
+ // Use boost::program_options for command-line options parsing
+
+ po::options_description desc("Available options");
+ desc.add_options()
+ ("help","produces this help message")
+ //("mesh-only","prevents the splitter from creating the fields contained in the original file(s)")
+ //("distributed","specifies that the input file is distributed")
+ ("input-file",po::value<string>(),"name of the input MED file")
+ ("output-file",po::value<string>(),"name of the resulting file")
+ //("meshname",po::value<string>(),"name of the input mesh")
+#ifdef ENABLE_PARMETIS
+#ifdef ENABLE_PTSCOTCH
+ ("split-method",po::value<string>(&library)->default_value("metis"),"name of the splitting library (metis,scotch)")
+#endif
+#endif
+ ("ndomains",po::value<int>(&ndomains)->default_value(1),"number of subdomains in the output file")
+ ("plain-master","creates a plain masterfile instead of an XML file")
+ ("creates-boundary-faces","creates the necessary faces so that faces joints are created in the output files")
+ ("family-splitting","preserves the family names instead of focusing on the groups")
+ ("empty-groups","creates empty groups in zones that do not contain a group from the original domain")
+ ("dump-cpu-memory","dumps passed CPU time and maximal increase of used memory");
+
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc,argv,desc),vm);
+ po::notify(vm);
+
+ if (vm.count("help"))
+ {
+ cout<<desc<<"\n";
+ return 1;
+ }
+
+ if (!vm.count("ndomains"))
+ {
+ cout << "ndomains must be specified !"<<endl;
+ return 1;
+ }
+
+ ndomains = vm["ndomains"].as<int>();
+ if (!vm.count("input-file") || !vm.count("output-file"))
+ {
+ cout << "input-file and output-file names must be specified"<<endl;
+ return 1;
+ }
+
+// if (!vm.count("distributed") && !vm.count("meshname") )
+// {
+// cout << "MEDPARTITIONER : for a serial MED file, mesh name must be selected with --meshname=..."<<endl;
+// return 1;
+// }
+
+ input = vm["input-file"].as<string>();
+ output = vm["output-file"].as<string>();
+
+// if (vm.count("mesh-only"))
+// mesh_only=true;
+
+// if (vm.count("distributed"))
+// is_sequential=false;
+
+// if (is_sequential)
+// meshname = vm["meshname"].as<string>();
+
+ if (vm.count("plain-master"))
+ xml_output_master=false;
+
+ if (vm.count("creates-boundary-faces"))
+ creates_boundary_faces=true;
+
+ if (vm.count("split-families"))
+ split_family=true;
+
+ if (vm.count("empty-groups"))
+ empty_groups=true;
+
+ if (vm.count("dump-cpu-memory"))
+ mesure_memory=true;
+
+#else // BOOST_PROGRAM_OPTIONS_LIB
+
+ // Primitive parsing of command-line options
+
+ string desc ("Available options:\n"
+ "\t--help : produces this help message\n"
+ //"\t--mesh-only : do not create the fields contained in the original file(s)\n"
+ //"\t--distributed : specifies that the input file is distributed\n"
+ "\t--input-file=<string> : name of the input MED file\n"
+ "\t--output-file=<string> : name of the resulting file\n"
+ //"\t--meshname=<string> : name of the input mesh (not used with --distributed option)\n"
+ "\t--ndomains=<number> : number of subdomains in the output file, default is 1\n"
+#ifdef ENABLE_PARMETIS
+#ifdef ENABLE_PTSCOTCH
+ "\t--split-method=<string> : name of the splitting library (metis/scotch), default is metis\n"
+#endif
+#endif
+ "\t--plain-master : creates a plain masterfile instead of an XML file\n"
+ "\t--creates-boundary-faces: creates the necessary faces so that faces joints are created in the output files\n"
+ "\t--family-splitting : preserves the family names instead of focusing on the groups\n"
+ "\t--dump-cpu-memory : dumps passed CPU time and maximal increase of used memory\n"
+ );
+
+ if (argc < 4) {
+ cout << desc.c_str() << endl;
+ return 1;
+ }
+
+ for (int i = 1; i < argc; i++) {
+ if (strlen(argv[i]) < 3) {
+ cout << desc.c_str() << endl;
+ return 1;
+ }
+
+/* if (strncmp(argv[i],"--m",3) == 0) {
+ if (strcmp(argv[i],"--mesh-only") == 0) {
+ mesh_only = true;
+ cout << "\tmesh-only = " << mesh_only << endl; // tmp
+ }
+ else if (strlen(argv[i]) > 11) { // "--meshname="
+ meshname = (argv[i] + 11);
+ cout << "\tmeshname = " << meshname << endl; // tmp
+ }
+ }
+ else if (strncmp(argv[i],"--d",3) == 0) {
+ is_sequential = false;
+ cout << "\tis_sequential = " << is_sequential << endl; // tmp
+ }
+ else */if (strncmp(argv[i],"--i",3) == 0) {
+ if (strlen(argv[i]) > 13) { // "--input-file="
+ input = (argv[i] + 13);
+ cout << "\tinput-file = " << input << endl; // tmp
+ }
+ }
+ else if (strncmp(argv[i],"--o",3) == 0) {
+ if (strlen(argv[i]) > 14) { // "--output-file="
+ output = (argv[i] + 14);
+ cout << "\toutput-file = " << output << endl; // tmp
+ }
+ }
+ else if (strncmp(argv[i],"--s",3) == 0) {
+ if (strlen(argv[i]) > 15) { // "--split-method="
+ library = (argv[i] + 15);
+ cout << "\tsplit-method = " << library << endl; // tmp
+ }
+ }
+ else if (strncmp(argv[i],"--f",3) == 0) { //"--family-splitting"
+ split_family=true;
+ cout << "\tfamily-splitting true" << endl; // tmp
+ }
+ else if (strncmp(argv[i],"--n",3) == 0) {
+ if (strlen(argv[i]) > 11) { // "--ndomains="
+ ndomains = atoi(argv[i] + 11);
+ cout << "\tndomains = " << ndomains << endl; // tmp
+ }
+ }
+ else if (strncmp(argv[i],"--p",3) == 0) { // "--plain-master"
+ xml_output_master = false;
+ cout << "\txml_output_master = " << xml_output_master << endl; // tmp
+ }
+ else if (strncmp(argv[i],"--c",3) == 0) { // "--creates-boundary-faces"
+ creates_boundary_faces = true;
+ cout << "\tcreates_boundary_faces = " << creates_boundary_faces << endl; // tmp
+ }
+ else if (strncmp(argv[i],"--e",3) == 0) { // "--empty-groups"
+ empty_groups = true;
+ cout << "\tempty_groups = true" << endl; // tmp
+ }
+ else if (strncmp(argv[i],"--d",3) == 0) { // "--dump-cpu-memory"
+ mesure_memory = true;
+ cout << "\tdump-cpu-memory = true" << endl; // tmp
+ }
+ else {
+ cout << desc.c_str() << endl;
+ return 1;
+ }
+ }
+
+// if (is_sequential && meshname.empty()) {
+// cout << "Mesh name must be given for sequential(not distributed) input file." << endl;
+// cout << desc << endl;
+// return 1;
+// }
+
+#endif // BOOST_PROGRAM_OPTIONS_LIB
+
+
+ //testing whether it is possible to write a file at the specified location
+ string outputtest = output + ".testioms.";
+ ofstream testfile (outputtest.c_str());
+ if (testfile.fail())
+ {
+ cout << "MEDPARTITIONER : output-file directory does not exist or is in read-only access" << endl;
+ return 1;
+ }
+ //deletes test file
+ remove(outputtest.c_str());
+
+ // Beginning of the computation
+
+ MPI_Init(&argc,&argv);
+
+
+ // Loading the mesh collection
+ cout << "MEDPARTITIONER - reading input files "<<endl;
+ MEDPARTITIONER::ParaDomainSelector parallelizer(mesure_memory);
+ MEDPARTITIONER::MESHCollection collection(input,parallelizer);
+
+ // Creating the graph and partitioning it
+ cout << "MEDPARTITIONER - computing partition "<<endl;
+#ifdef ENABLE_PARMETIS
+#ifndef ENABLE_PTSCOTCH
+ library = "metis";
+#endif
+#else
+ library = "scotch";
+#endif
+ cout << "\tsplit-method = " << library << endl; // tmp
+
+ auto_ptr< MEDPARTITIONER::Topology > new_topo;
+ if (library == "metis")
+ new_topo.reset( collection.createPartition(ndomains,MEDPARTITIONER::Graph::METIS));
+ else
+ new_topo.reset( collection.createPartition(ndomains,MEDPARTITIONER::Graph::SCOTCH));
+ parallelizer.evaluateMemory();
+
+ // Creating a new mesh collection from the partitioning
+ cout << "MEDPARTITIONER - creating new meshes"<<endl;
+ MEDPARTITIONER::MESHCollection new_collection(collection,new_topo.get(),split_family,empty_groups);
+ parallelizer.evaluateMemory();
+
+ if (!xml_output_master)
+ new_collection.setDriverType(MEDPARTITIONER::MedAscii);
+
+ // new_collection.setSubdomainBoundaryCreates(creates_boundary_faces);
+
+ cout << "MEDPARTITIONER - writing output files "<<endl;
+ new_collection.write(output);
+
+ if ( mesure_memory )
+ if ( parallelizer.isOnDifferentHosts() || parallelizer.rank()==0 )
+ {
+ MEDMEM::STRING text("proc ");
+ text << parallelizer.rank() << ": elapsed time = " << parallelizer.getPassedTime()
+ << ", max memory usage = " << parallelizer.evaluateMemory() << " KB";
+ cout << text << endl;
+ }
+ // Casting the fields on the new collection
+// if (!mesh_only)
+// new_collection.castAllFields(*collection);
+
+ MPI_Finalize();
+
+ return 0;
+}