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
27 #include <libxml/tree.h>
28 #include <libxml/parser.h>
29 #include <libxml/xpath.h>
30 #include <libxml/xpathInternals.h>
39 #include "MEDMEM_Utilities.hxx"
42 #include "MEDMEM_DriversDef.hxx"
43 #include "MEDMEM_Mesh.hxx"
44 #include "MEDMEM_Field.hxx"
45 #include "MEDMEM_Meshing.hxx"
46 #include "MEDMEM_CellModel.hxx"
47 #include "MEDMEM_SkyLineArray.hxx"
48 #include "MEDMEM_ConnectZone.hxx"
50 //MEDSPLITTER includes
51 #include "MEDSPLITTER_Topology.hxx"
52 #include "MEDSPLITTER_ParallelTopology.hxx"
53 #include "MEDSPLITTER_SequentialTopology.hxx"
54 #include "MEDSPLITTER_MESHCollectionDriver.hxx"
55 #include "MEDSPLITTER_MESHCollection.hxx"
56 #include "MEDSPLITTER_MESHCollectionMedXMLDriver.hxx"
57 #include "MEDSPLITTER_ParaDomainSelector.hxx"
59 using namespace MEDSPLITTER;
62 #include "MEDSPLITTER_MESHCollectionMedXMLDriver.H"
64 /*!\class MESHCollectionMedXMLDriver
66 *\brief Driver for MED 3.2 files having XML master files
68 * Driver for reading and writing distributed files
69 * for which the master file is written in an XML format compliant with
70 * the MED 3.2 specification.
71 * The reading and writing of the meshes and fields are apart :
72 * the meshes must always be written/read before the fields. Reading/Writing fields
73 * is optional and is done field after field. API for reading/writing fields
74 * is written with a template so that MEDMEM::FIELD<int> and MEDMEM::FIELD<double>
75 * can be conveniently handled.
78 MESHCollectionMedXMLDriver::MESHCollectionMedXMLDriver(MESHCollection* collection):MESHCollectionDriver(collection)
82 /*!reads a MED File XML Master File v>=2.3
83 * and mounts the corresponding meshes in memory
84 * the connect zones are created from the joints
86 *\param filename XML file containing the list of MED v2.3 files
89 int MESHCollectionMedXMLDriver::read(char* filename, ParaDomainSelector* domainSelector)
91 const char* LOC = "MEDSPLITTER::MESHCollectionDriver::read()";
95 vector<int*> cellglobal;
96 vector<int*> nodeglobal;
97 vector<int*> faceglobal;
101 _master_filename=filename;
103 // reading ascii master file
106 MESSAGE_MED("Start reading");
108 // Setting up the XML tree corresponding to filename
109 xmlDocPtr master_doc=xmlParseFile(filename);
112 throw MEDEXCEPTION("MEDSPLITTER XML read - Master File does not exist o r is not compliant with XML scheme");
117 xmlXPathContextPtr xpathCtx = xmlXPathNewContext(master_doc);
118 xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression(BAD_CAST "//splitting/subdomain", xpathCtx);
119 if (xpathObj==0 || xpathObj->nodesetval->nodeNr ==0)
121 xmlXPathFreeObject(xpathObj);
122 throw MEDEXCEPTION("MEDSPLITTER read - XML Master File does not contain /MED/splitting/subdomain node");
124 /* as subdomain has only one property which is "number"
125 * it suffices to take the content of its first child */
126 const char* mystring = (const char*)xpathObj->nodesetval->nodeTab[0]->properties->children->content;
127 sscanf(mystring, "%d", &nbdomain);
132 xmlXPathFreeObject(xpathObj);
133 xpathObj = xmlXPathEvalExpression(BAD_CAST "//content/mesh", xpathCtx);
134 if (xpathObj==0 || xpathObj->nodesetval->nodeNr ==0)
136 xmlXPathFreeObject(xpathObj);
137 throw MEDEXCEPTION("MEDSPLITTER read - XML Master File does not contain /MED/content/mesh node");
139 _collection->setName( (const char*)xpathObj->nodesetval->nodeTab[0]->properties->children->content);
141 cout << "nb domain " << nbdomain << endl;
142 _filename.resize(nbdomain);
143 _meshname.resize(nbdomain);
144 (_collection->getMesh()).resize(nbdomain);
145 cellglobal.resize(nbdomain);
146 nodeglobal.resize(nbdomain);
147 faceglobal.resize(nbdomain);
150 // retrieving the node which contains the file names
151 const char filechar[]="//files/subfile";
152 xmlXPathFreeObject(xpathObj);
153 xpathObj = xmlXPathEvalExpression(BAD_CAST filechar, xpathCtx);
154 if (xpathObj==0 || xpathObj->nodesetval->nodeNr ==0)
156 xmlXPathFreeObject(xpathObj);
157 throw MEDEXCEPTION("MEDSPLITTER read - XML Master File does not contain /MED/files/subfile nodes");
159 int nbfiles = xpathObj->nodesetval ->nodeNr;
161 for (int i=0; i<nbfiles;i++)
163 //reading information about the domain
171 ////////////////////////////
173 ////////////////////////////
174 ostringstream name_search_string;
175 name_search_string<<"//files/subfile[@id=\""<<i+1<<"\"]/name";
176 //cout <<name_search_string.str()<<endl;
177 xmlXPathObjectPtr xpathObjfilename =
178 xmlXPathEvalExpression(BAD_CAST name_search_string.str().c_str(),xpathCtx);
179 if (xpathObjfilename->nodesetval ==0)
180 throw MEDEXCEPTION("MED XML reader : Error retrieving file name ");
181 _filename[i]=(const char*)xpathObjfilename->nodesetval->nodeTab[0]->children->content;
183 ////////////////////////////////
184 //reading the local mesh names
185 ////////////////////////////////
186 ostringstream mesh_search_string;
187 mesh_search_string<<"//mapping/mesh/chunk[@subdomain=\""<<i+1<<"\"]/name";
189 xmlXPathObjectPtr xpathMeshObj = xmlXPathEvalExpression(BAD_CAST mesh_search_string.str().c_str(),xpathCtx);
190 if (xpathMeshObj->nodesetval ==0)
191 throw MEDEXCEPTION("MED XML reader : Error retrieving mesh name ");
192 _meshname[i]=(const char*)xpathMeshObj->nodesetval->nodeTab[0]->children->content;
194 if ( !domainSelector || domainSelector->isMyDomain(i))
195 readSubdomain(cellglobal, faceglobal, nodeglobal, i);
196 xmlXPathFreeObject(xpathObjfilename);
198 xmlXPathFreeObject(xpathMeshObj);
202 xmlXPathFreeObject(xpathObj);
203 xmlXPathFreeContext(xpathCtx);
204 xmlFreeDoc(master_doc);
206 MESSAGE_MED("end of read");
210 throw MEDEXCEPTION("I/O error reading parallel MED file");
213 //creation of topology from mesh and connect zones
214 ParallelTopology* aPT = new ParallelTopology
215 ((_collection->getMesh()), (_collection->getCZ()), cellglobal, nodeglobal, faceglobal);
216 _collection->setTopology(aPT);
218 for (int i=0; i<nbdomain; i++)
220 if (cellglobal[i]!=0) delete[] cellglobal[i];
221 if (nodeglobal[i]!=0) delete[] nodeglobal[i];
222 if (faceglobal[i]!=0) delete[] faceglobal[i];
230 /*! writes the collection of meshes in a
232 * with the connect zones being written as joints
233 * \param filename name of the XML file containing the meshes description
235 void MESHCollectionMedXMLDriver::write(char* filename, ParaDomainSelector* domainSelector)
237 const char* LOC = "MEDSPLITTER::MESHCollectionDriver::writeXML()";
240 xmlDocPtr master_doc = 0;
241 xmlNodePtr root_node = 0, node, node2;
242 // xmlDTDPtr dtd = 0;
246 //Creating the XML document
248 master_doc = xmlNewDoc(BAD_CAST "1.0");
249 root_node = xmlNewNode(0, BAD_CAST "root");
250 xmlDocSetRootElement(master_doc,root_node);
252 //Creating child nodes
255 node = xmlNewChild(root_node, 0, BAD_CAST "version",0);
256 xmlNewProp(node, BAD_CAST "maj", BAD_CAST "2");
257 xmlNewProp(node, BAD_CAST "min", BAD_CAST "3");
258 xmlNewProp(node, BAD_CAST "ver", BAD_CAST "1");
265 struct tm *time_asc = localtime(&present);
266 sprintf(date,"%02d%02d%02d",time_asc->tm_year
271 GetLocalTime ( &st );
272 sprintf(date,"%02d%02d%02d",
278 node = xmlNewChild(root_node,0, BAD_CAST "description",0);
280 xmlNewProp(node, BAD_CAST "what", BAD_CAST _collection->getDescription().c_str());
281 xmlNewProp(node, BAD_CAST "when", BAD_CAST date);
284 node =xmlNewChild(root_node,0, BAD_CAST "content",0);
285 node2 = xmlNewChild(node, 0, BAD_CAST "mesh",0);
286 xmlNewProp(node2, BAD_CAST "name", BAD_CAST _collection->getName().c_str());
289 node=xmlNewChild(root_node,0,BAD_CAST "splitting",0);
290 node2=xmlNewChild(node,0,BAD_CAST "subdomain",0);
291 sprintf(buff, "%d", (int)_collection->getMesh().size());
292 xmlNewProp(node2, BAD_CAST "number", BAD_CAST buff);
293 node2=xmlNewChild(node,0,BAD_CAST "global_numbering",0);
294 xmlNewProp(node2, BAD_CAST "present", BAD_CAST "yes");
297 xmlNodePtr file_node=xmlNewChild(root_node,0,BAD_CAST "files",0);
300 node = xmlNewChild(root_node,0,BAD_CAST "mapping",0);
301 xmlNodePtr mesh_node = xmlNewChild(node, 0, BAD_CAST "mesh",0);
302 xmlNewProp(mesh_node, BAD_CAST "name", BAD_CAST _collection->getName().c_str());
304 int nbdomains= _collection->getMesh().size();
305 _filename.resize(nbdomains);
307 //loop on the domains
308 for (int idomain=nbdomains-1; idomain>=0;idomain--)
310 char distfilename[256];
312 ostringstream suffix;
313 suffix << filename<< idomain+1 <<".med";
315 strcpy(distfilename,suffix.str().c_str());
317 _filename[idomain]=string(distfilename);
319 MESSAGE_MED("File name "<<string(distfilename));
321 if ( !domainSelector || domainSelector->isMyDomain( idomain ) )
323 if ( !_collection->getMesh()[idomain]->getConnectivityptr() ) continue;//empty domain
325 int id=(_collection->getMesh())[idomain]->addDriver(MEDMEM::MED_DRIVER,distfilename,(_collection->getMesh())[idomain]->getName(),MED_EN::WRONLY);
327 MESSAGE_MED("Start writing");
328 (_collection->getMesh())[idomain]->write(id);
329 (_collection->getMesh())[idomain]->rmDriver(id);
331 writeSubdomain(idomain, nbdomains, distfilename, domainSelector);
333 //updating the ascii description file
334 node = xmlNewChild(file_node, 0, BAD_CAST "subfile",0);
335 sprintf (buff,"%d",idomain+1);
336 xmlNewProp(node, BAD_CAST "id", BAD_CAST buff);
337 xmlNewChild(node,0,BAD_CAST "name",BAD_CAST distfilename);
338 xmlNewChild(node,0,BAD_CAST "machine",BAD_CAST "localhost");
340 node = xmlNewChild(mesh_node,0, BAD_CAST "chunk",0);
341 xmlNewProp(node, BAD_CAST "subdomain", BAD_CAST buff);
342 xmlNewChild(node,0,BAD_CAST "name", BAD_CAST (_collection->getMesh())[idomain]->getName().c_str());
344 strcat(filename,".xml");
345 _master_filename=filename;
346 if ( !domainSelector || domainSelector->rank() == 0 )
347 xmlSaveFormatFileEnc(filename, master_doc, "UTF-8", 1);
348 xmlFreeDoc(master_doc);
349 //xmlCleanupParser();