Salome HOME
Merge from V6_main 01/04/2013
[modules/med.git] / src / MEDSPLITTER / MEDSPLITTER_MESHCollectionMedXMLDriver.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 #include <vector>
20 #include <string>
21 #include <map>
22 #include <set>
23
24 #include <iostream>
25 #include <fstream>
26
27 #include <libxml/tree.h>
28 #include <libxml/parser.h>
29 #include <libxml/xpath.h>
30 #include <libxml/xpathInternals.h>
31
32 #ifndef WIN32
33 #include <sys/time.h>
34 #else
35 #include <time.h>
36 #include <windows.h>
37 #endif
38 //Debug macros
39 #include "MEDMEM_Utilities.hxx"
40
41 //MEDMEM includes
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"
49
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"
58
59 using namespace MEDSPLITTER;
60
61 //template inclusion
62 #include "MEDSPLITTER_MESHCollectionMedXMLDriver.H"
63
64 /*!\class MESHCollectionMedXMLDriver
65  *
66  *\brief Driver for MED 3.2 files having XML master files
67  *
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.
76 */
77
78 MESHCollectionMedXMLDriver::MESHCollectionMedXMLDriver(MESHCollection* collection):MESHCollectionDriver(collection)
79 {
80 }
81
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
85  * 
86  *\param filename XML file containing the list of MED v2.3 files
87  * */
88
89 int MESHCollectionMedXMLDriver::read(char* filename, ParaDomainSelector* domainSelector)
90 {
91   const char* LOC = "MEDSPLITTER::MESHCollectionDriver::read()";
92   BEGIN_OF_MED(LOC);
93
94   //ditributed meshes
95   vector<int*> cellglobal;
96   vector<int*> nodeglobal;
97   vector<int*> faceglobal;
98
99   int nbdomain;
100
101   _master_filename=filename;
102
103   // reading ascii master file
104   try
105     {
106       MESSAGE_MED("Start reading");
107
108       // Setting up the XML tree corresponding to filename
109       xmlDocPtr master_doc=xmlParseFile(filename);
110
111       if (!master_doc)    
112         throw MEDEXCEPTION("MEDSPLITTER XML read - Master File does not exist o r is not compliant with XML scheme");
113
114       ////////////////////
115       //number of domains
116       ////////////////////
117       xmlXPathContextPtr xpathCtx = xmlXPathNewContext(master_doc);
118       xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression(BAD_CAST "//splitting/subdomain", xpathCtx);
119       if (xpathObj==0 || xpathObj->nodesetval->nodeNr ==0)
120         {
121           xmlXPathFreeObject(xpathObj);
122           throw MEDEXCEPTION("MEDSPLITTER read - XML Master File does not contain /MED/splitting/subdomain node");
123         }
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);
128
129       //////////////////
130       //mesh name
131       //////////////////
132       xmlXPathFreeObject(xpathObj);
133       xpathObj = xmlXPathEvalExpression(BAD_CAST "//content/mesh", xpathCtx);
134       if (xpathObj==0 || xpathObj->nodesetval->nodeNr ==0)
135         {
136           xmlXPathFreeObject(xpathObj);
137           throw MEDEXCEPTION("MEDSPLITTER read - XML Master File does not contain /MED/content/mesh node");
138         }
139       _collection->setName( (const char*)xpathObj->nodesetval->nodeTab[0]->properties->children->content);
140
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);
148
149
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)
155         {
156           xmlXPathFreeObject(xpathObj);
157           throw MEDEXCEPTION("MEDSPLITTER read - XML Master File does not contain /MED/files/subfile nodes");
158         }
159       int nbfiles = xpathObj->nodesetval ->nodeNr;
160
161       for (int i=0; i<nbfiles;i++)
162         {
163           //reading information about the domain
164
165           string host;
166
167           cellglobal[i]=0;
168           faceglobal[i]=0;
169           nodeglobal[i]=0;
170
171           ////////////////////////////
172           //reading file names 
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;
182
183           ////////////////////////////////
184           //reading the local mesh names
185           ////////////////////////////////
186           ostringstream mesh_search_string;
187           mesh_search_string<<"//mapping/mesh/chunk[@subdomain=\""<<i+1<<"\"]/name";
188
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;
193
194           if ( !domainSelector || domainSelector->isMyDomain(i))
195             readSubdomain(cellglobal, faceglobal, nodeglobal, i);
196           xmlXPathFreeObject(xpathObjfilename);
197
198           xmlXPathFreeObject(xpathMeshObj);
199         }//loop on domains
200
201       // LIBXML cleanup
202       xmlXPathFreeObject(xpathObj);
203       xmlXPathFreeContext(xpathCtx);
204       xmlFreeDoc(master_doc);
205
206       MESSAGE_MED("end of read");
207     }//of try
208   catch(...)
209     {
210       throw MEDEXCEPTION("I/O error reading parallel MED file");
211     }
212
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);
217
218   for (int i=0; i<nbdomain; i++)
219     {
220       if (cellglobal[i]!=0) delete[] cellglobal[i];
221       if (nodeglobal[i]!=0) delete[] nodeglobal[i];
222       if (faceglobal[i]!=0) delete[] faceglobal[i];
223     }
224
225   END_OF_MED(LOC);
226   return 0;
227 }
228
229
230 /*! writes the collection of meshes in a 
231  * MED v2.3 XML file
232  * with the connect zones being written as joints
233  * \param filename name of the XML file containing the meshes description
234  */
235 void MESHCollectionMedXMLDriver::write(char* filename, ParaDomainSelector* domainSelector)
236 {
237   const char* LOC = "MEDSPLITTER::MESHCollectionDriver::writeXML()";
238   BEGIN_OF_MED(LOC);
239
240   xmlDocPtr master_doc = 0;
241   xmlNodePtr root_node = 0, node, node2;
242   //  xmlDTDPtr dtd = 0;
243
244   char buff[256];
245
246   //Creating the XML document
247
248   master_doc = xmlNewDoc(BAD_CAST "1.0");
249   root_node = xmlNewNode(0, BAD_CAST "root");
250   xmlDocSetRootElement(master_doc,root_node);
251
252   //Creating child nodes
253
254   // Version tag
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");
259
260   //Description tag
261   char date[1024];
262 #ifndef WIN32
263   time_t present;
264   time( &present);
265   struct tm *time_asc = localtime(&present);
266   sprintf(date,"%02d%02d%02d",time_asc->tm_year
267           ,time_asc->tm_mon+1
268           ,time_asc->tm_mday);
269 #else
270   SYSTEMTIME    st;
271   GetLocalTime ( &st );
272   sprintf(date,"%02d%02d%02d",
273           st.wYear
274           ,st.wMonth
275           ,st.wDay);
276 #endif
277
278   node = xmlNewChild(root_node,0, BAD_CAST "description",0);
279
280   xmlNewProp(node, BAD_CAST "what", BAD_CAST _collection->getDescription().c_str());
281   xmlNewProp(node, BAD_CAST "when", BAD_CAST date);
282
283   //Content tag
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());
287
288   //Splitting tag
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");
295
296   //Files tag
297   xmlNodePtr file_node=xmlNewChild(root_node,0,BAD_CAST "files",0);
298
299   //Mapping tag
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());
303
304   int nbdomains= _collection->getMesh().size();
305   _filename.resize(nbdomains);
306
307   //loop on the domains
308   for (int idomain=nbdomains-1; idomain>=0;idomain--)
309     {
310       char distfilename[256];
311
312       ostringstream suffix;
313       suffix << filename<< idomain+1 <<".med";
314
315       strcpy(distfilename,suffix.str().c_str());
316
317       _filename[idomain]=string(distfilename);
318
319       MESSAGE_MED("File name "<<string(distfilename));
320
321       if ( !domainSelector || domainSelector->isMyDomain( idomain ) )
322         {
323           if ( !_collection->getMesh()[idomain]->getConnectivityptr() ) continue;//empty domain
324
325           int id=(_collection->getMesh())[idomain]->addDriver(MEDMEM::MED_DRIVER,distfilename,(_collection->getMesh())[idomain]->getName(),MED_EN::WRONLY);
326
327           MESSAGE_MED("Start writing");
328           (_collection->getMesh())[idomain]->write(id);
329           (_collection->getMesh())[idomain]->rmDriver(id);
330
331           writeSubdomain(idomain, nbdomains, distfilename, domainSelector);
332         }
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");
339
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());
343     }
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();
350
351   END_OF_MED(LOC);
352 }