]> SALOME platform Git repositories - tools/medcoupling.git/commitdiff
Salome HOME
*** empty log message ***
authorvbd <vbd>
Wed, 20 Jul 2011 17:02:06 +0000 (17:02 +0000)
committervbd <vbd>
Wed, 20 Jul 2011 17:02:06 +0000 (17:02 +0000)
src/MEDPartitioner/MEDPARTITIONER_MESHCollectionMedAsciiDriver.cxx [new file with mode: 0644]
src/MEDPartitioner/MEDPARTITIONER_MESHCollectionMedXMLDriver.cxx [new file with mode: 0644]
src/MEDPartitioner/medsplitter.cxx [new file with mode: 0644]
src/MEDPartitioner/medsplitter_para.cxx [new file with mode: 0644]

diff --git a/src/MEDPartitioner/MEDPARTITIONER_MESHCollectionMedAsciiDriver.cxx b/src/MEDPartitioner/MEDPARTITIONER_MESHCollectionMedAsciiDriver.cxx
new file mode 100644 (file)
index 0000000..8492681
--- /dev/null
@@ -0,0 +1,223 @@
+//  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);
+
+}
diff --git a/src/MEDPartitioner/MEDPARTITIONER_MESHCollectionMedXMLDriver.cxx b/src/MEDPartitioner/MEDPARTITIONER_MESHCollectionMedXMLDriver.cxx
new file mode 100644 (file)
index 0000000..2e20bd4
--- /dev/null
@@ -0,0 +1,323 @@
+//  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);
+
+}
diff --git a/src/MEDPartitioner/medsplitter.cxx b/src/MEDPartitioner/medsplitter.cxx
new file mode 100644 (file)
index 0000000..114145c
--- /dev/null
@@ -0,0 +1,315 @@
+//  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;
+}
diff --git a/src/MEDPartitioner/medsplitter_para.cxx b/src/MEDPartitioner/medsplitter_para.cxx
new file mode 100644 (file)
index 0000000..04ac900
--- /dev/null
@@ -0,0 +1,327 @@
+//  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;
+}