Back to index

salome-med  6.5.0
MEDPARTITIONER_MeshCollectionMedXmlDriver.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 #include "MEDPARTITIONER_ParallelTopology.hxx"
00021 #include "MEDPARTITIONER_MeshCollectionDriver.hxx"
00022 #include "MEDPARTITIONER_MeshCollection.hxx"
00023 #include "MEDPARTITIONER_MeshCollectionMedXmlDriver.hxx"
00024 #include "MEDPARTITIONER_ParaDomainSelector.hxx"
00025 #include "MEDPARTITIONER_Utils.hxx"
00026 
00027 #include "MEDCouplingUMesh.hxx"
00028 #include "MEDLoader.hxx"
00029 #include "MEDFileMesh.hxx"
00030 
00031 #include <map>
00032 #include <set>
00033 #include <vector>
00034 #include <string>
00035 #include <cstring>
00036 #include <fstream>
00037 #include <sstream>
00038 #include <iostream>
00039 #ifdef WIN32
00040 #include <time.h>
00041 #include <windows.h>
00042 #endif
00043 
00044 
00045 #include <libxml/tree.h>
00046 #include <libxml/parser.h>
00047 #include <libxml/xpath.h>
00048 #include <libxml/xpathInternals.h>
00049 
00050 using namespace MEDPARTITIONER;
00051 
00066 MeshCollectionMedXmlDriver::MeshCollectionMedXmlDriver(MeshCollection* collection):MeshCollectionDriver(collection)
00067 {
00068 }
00069 
00077 int MeshCollectionMedXmlDriver::read(const char* filename, ParaDomainSelector* domainSelector)
00078 {
00079   //distributed meshes
00080   int nbdomain;
00081   _master_filename=filename;
00082 
00083   //reading ascii master file
00084   try
00085     {
00086       //Setting up the Xml tree corresponding to filename
00087       xmlDocPtr master_doc=xmlParseFile(filename);
00088 
00089       if (!master_doc)
00090         throw INTERP_KERNEL::Exception("Xml Master File does not exist or is not compliant with Xml scheme");
00091 
00092       //number of domains
00093       xmlXPathContextPtr xpathCtx = xmlXPathNewContext(master_doc);
00094       xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression(BAD_CAST "//splitting/subdomain", xpathCtx);
00095       if (xpathObj==0 || xpathObj->nodesetval->nodeNr ==0)
00096         throw INTERP_KERNEL::Exception("Xml Master File does not contain /MED/splitting/subdomain node");
00097 
00098       //as subdomain has only one property which is "number"
00099       //it suffices to take the content of its first child 
00100       const char* mystring = (const char*)xpathObj->nodesetval->nodeTab[0]->properties->children->content;
00101       sscanf(mystring, "%d", &nbdomain);
00102 
00103       //mesh name
00104       xmlXPathFreeObject(xpathObj);
00105       xpathObj = xmlXPathEvalExpression(BAD_CAST "//content/mesh", xpathCtx);
00106       if (xpathObj==0 || xpathObj->nodesetval->nodeNr ==0)
00107         throw INTERP_KERNEL::Exception("Xml Master File does not contain /MED/content/mesh node");
00108       _collection->setName( (const char*)xpathObj->nodesetval->nodeTab[0]->properties->children->content);
00109 
00110       //cout << "nb domain " << nbdomain << endl;
00111       MyGlobals::_File_Names.resize(nbdomain);
00112       MyGlobals::_Mesh_Names.resize(nbdomain);
00113       (_collection->getMesh()).resize(nbdomain);
00114       (_collection->getFaceMesh()).resize(nbdomain);
00115       (_collection->getCellFamilyIds()).resize(nbdomain);
00116       (_collection->getFaceFamilyIds()).resize(nbdomain);
00117 
00118       //retrieving the node which contains the file names
00119       const char filechar[]="//files/subfile";
00120       xmlXPathFreeObject(xpathObj);
00121       xpathObj = xmlXPathEvalExpression(BAD_CAST filechar, xpathCtx);
00122       if (xpathObj==0 || xpathObj->nodesetval->nodeNr ==0)
00123         throw INTERP_KERNEL::Exception("Xml Master File does not contain /MED/files/subfile nodes");
00124       int nbfiles = xpathObj->nodesetval ->nodeNr;
00125     
00126       for (int i=0; i<nbfiles;i++)
00127         {
00128           //reading information about the domain
00129           std::string host;
00130           //reading file names 
00131           std::ostringstream name_search_string;
00132           name_search_string<<"//files/subfile[@id=\""<<i+1<<"\"]/name";
00133           xmlXPathObjectPtr xpathObjfilename =
00134             xmlXPathEvalExpression(BAD_CAST name_search_string.str().c_str(),xpathCtx);
00135           if (xpathObjfilename->nodesetval ==0)
00136             throw INTERP_KERNEL::Exception("Error retrieving a file name from subfile of Xml Master File");
00137           MyGlobals::_File_Names[i]=(const char*)xpathObjfilename->nodesetval->nodeTab[0]->children->content;
00138 
00139           //reading the local mesh names
00140           std::ostringstream mesh_search_string;
00141           mesh_search_string<<"//mapping/mesh/chunk[@subdomain=\""<<i+1<<"\"]/name";
00142 
00143           xmlXPathObjectPtr xpathMeshObj = xmlXPathEvalExpression(BAD_CAST mesh_search_string.str().c_str(),xpathCtx);
00144           if (xpathMeshObj->nodesetval ==0)
00145             throw INTERP_KERNEL::Exception("Error retrieving mesh name from chunk of Xml Master File");
00146           MyGlobals::_Mesh_Names[i]=(const char*)xpathMeshObj->nodesetval->nodeTab[0]->children->content;
00147 
00148           if ( !domainSelector || domainSelector->isMyDomain(i))
00149             readSubdomain(i);
00150           xmlXPathFreeObject(xpathObjfilename);
00151           xmlXPathFreeObject(xpathMeshObj);
00152         } //loop on domains
00153 
00154       //LIBXML cleanup
00155       xmlXPathFreeObject(xpathObj); 
00156       xmlXPathFreeContext(xpathCtx); 
00157       xmlFreeDoc(master_doc); 
00158 
00159     } //of try
00160   catch(...)
00161     {
00162       throw INTERP_KERNEL::Exception("I/O error reading parallel MED file");
00163     }
00164 
00165   ParallelTopology* aPT = new ParallelTopology(_collection->getMesh());
00166   //creation of topology from mesh and connect zones
00167   if ( _collection->isParallelMode() )
00168     {
00169       //to know nb of cells on each proc to compute global cell ids from locally global
00170       domainSelector->gatherNbOf(_collection->getMesh());
00171     }
00172   _collection->setTopology(aPT);
00173   _collection->setDomainNames(_collection->getName());
00174   return 0;
00175 }
00176 
00177 
00183 void MeshCollectionMedXmlDriver::write(const char* filename, ParaDomainSelector* domainSelector) const
00184 {
00185   xmlDocPtr master_doc = 0;
00186   xmlNodePtr root_node = 0, node, node2;
00187   char buff[256];
00188 
00189   //Creating the Xml document
00190   master_doc = xmlNewDoc(BAD_CAST "1.0");
00191   root_node = xmlNewNode(0, BAD_CAST "root");
00192   xmlDocSetRootElement(master_doc,root_node);
00193 
00194   //Creating child nodes
00195   // Version tag
00196   node = xmlNewChild(root_node, 0, BAD_CAST "version",0);
00197   xmlNewProp(node, BAD_CAST "maj", BAD_CAST "2");
00198   xmlNewProp(node, BAD_CAST "min", BAD_CAST "3");
00199   xmlNewProp(node, BAD_CAST "ver", BAD_CAST "1");
00200 
00201   //Description tag
00202   time_t present; 
00203   char date[6];
00204 #ifndef WIN32
00205   time( &present);
00206   struct tm *time_asc = localtime(&present);
00207   sprintf(date,"%02d%02d%02d",time_asc->tm_year
00208           ,time_asc->tm_mon+1
00209           ,time_asc->tm_mday);
00210 #else
00211   SYSTEMTIME    st;
00212   GetLocalTime ( &st );
00213   sprintf(date,"%02d%02d%02d",
00214           st.wYear
00215           ,st.wMonth
00216           ,st.wDay);
00217 #endif
00218 
00219   node = xmlNewChild(root_node,0, BAD_CAST "description",0);
00220 
00221   xmlNewProp(node, BAD_CAST "what", BAD_CAST _collection->getDescription().c_str());
00222   xmlNewProp(node, BAD_CAST "when", BAD_CAST date);
00223 
00224   //Content tag
00225   node =xmlNewChild(root_node,0, BAD_CAST "content",0);
00226   node2 = xmlNewChild(node, 0, BAD_CAST "mesh",0);
00227   xmlNewProp(node2, BAD_CAST "name", BAD_CAST _collection->getName().c_str());
00228 
00229   //Splitting tag
00230   node=xmlNewChild(root_node,0,BAD_CAST "splitting",0);
00231   node2=xmlNewChild(node,0,BAD_CAST "subdomain",0);
00232   sprintf(buff, "%d", (int)_collection->getMesh().size());
00233   xmlNewProp(node2, BAD_CAST "number", BAD_CAST buff);
00234   node2=xmlNewChild(node,0,BAD_CAST "global_numbering",0);
00235   xmlNewProp(node2, BAD_CAST "present", BAD_CAST "yes");
00236 
00237   //Files tag
00238   xmlNodePtr file_node=xmlNewChild(root_node,0,BAD_CAST "files",0);
00239 
00240   //Mapping tag
00241   node = xmlNewChild(root_node,0,BAD_CAST "mapping",0);
00242   xmlNodePtr mesh_node = xmlNewChild(node, 0, BAD_CAST "mesh",0);
00243   xmlNewProp(mesh_node, BAD_CAST "name", BAD_CAST _collection->getName().c_str());
00244 
00245   int nbdomains= _collection->getMesh().size();
00246 
00247   //loop on the domains
00248   std::string finalMeshName=ExtractFromDescription(MyGlobals::_General_Informations[0], "finalMeshName=");
00249   for (int idomain=nbdomains-1; idomain>=0;idomain--)
00250     {
00251       std::string distfilename;
00252       std::ostringstream suffix;
00253       suffix<<filename<<idomain+1<<".med";
00254       distfilename=suffix.str();
00255 
00256       if ( !domainSelector || domainSelector->isMyDomain( idomain ) )
00257         {
00258           if ( (_collection->getMesh())[idomain]->getNumberOfCells()==0 )
00259             continue; //empty domain
00260           if (MyGlobals::_Verbose>1)
00261             std::cout << "proc "<< domainSelector->rank() << " : writeMedFile " << distfilename
00262                       << " "<< (_collection->getMesh())[idomain]->getNumberOfCells() << " cells"
00263                       << " " << (_collection->getFaceMesh())[idomain]->getNumberOfCells() << " faces"
00264                       << " " << (_collection->getMesh())[idomain]->getNumberOfNodes()<<" nodes" << std::endl;
00265           writeMedFile(idomain,distfilename);
00266         }
00267 
00268       if (domainSelector->rank()==0)
00269         {
00270           //updating the ascii description file
00271           node = xmlNewChild(file_node, 0, BAD_CAST "subfile",0);
00272           sprintf (buff,"%d",idomain+1);
00273           xmlNewProp(node, BAD_CAST "id", BAD_CAST buff);
00274           xmlNewChild(node,0,BAD_CAST "name",BAD_CAST distfilename.c_str());
00275           xmlNewChild(node,0,BAD_CAST "machine",BAD_CAST "localhost");
00276 
00277           node = xmlNewChild(mesh_node,0, BAD_CAST "chunk",0);
00278           xmlNewProp(node, BAD_CAST "subdomain", BAD_CAST buff);
00279           xmlNewChild(node,0,BAD_CAST "name", BAD_CAST finalMeshName.c_str());
00280           //xmlNewChild(node,0,BAD_CAST "name", BAD_CAST (_collection->getMesh())[idomain]->getName());
00281         }
00282     }
00283   
00284   //create the ascii description file
00285   if (domainSelector->rank()==0)
00286     {
00287       std::string myfile(filename);
00288       myfile.append(".xml");
00289       if ( !domainSelector || domainSelector->rank() == 0 )
00290         xmlSaveFormatFileEnc(myfile.c_str(), master_doc, "UTF-8", 1);
00291     }
00292   xmlFreeDoc(master_doc);
00293   xmlCleanupParser();
00294 }