XdmfMeshWriter.cpp

00001 /*
00002 
00003 Copyright (c) 2005-2015, University of Oxford.
00004 All rights reserved.
00005 
00006 University of Oxford means the Chancellor, Masters and Scholars of the
00007 University of Oxford, having an administrative office at Wellington
00008 Square, Oxford OX1 2JD, UK.
00009 
00010 This file is part of Chaste.
00011 
00012 Redistribution and use in source and binary forms, with or without
00013 modification, are permitted provided that the following conditions are met:
00014  * Redistributions of source code must retain the above copyright notice,
00015    this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright notice,
00017    this list of conditions and the following disclaimer in the documentation
00018    and/or other materials provided with the distribution.
00019  * Neither the name of the University of Oxford nor the names of its
00020    contributors may be used to endorse or promote products derived from this
00021    software without specific prior written permission.
00022 
00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 
00034 */
00035 
00036 #include <sstream>
00037 #include <map>
00038 
00039 #include "XdmfMeshWriter.hpp"
00040 #include "DistributedTetrahedralMesh.hpp"
00041 #include "Version.hpp"
00042 
00043 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00044 XdmfMeshWriter<ELEMENT_DIM, SPACE_DIM>::XdmfMeshWriter(const std::string& rDirectory,
00045                                                        const std::string& rBaseName,
00046                                                        const bool clearOutputDir)
00047     : AbstractTetrahedralMeshWriter<ELEMENT_DIM, SPACE_DIM>(rDirectory, rBaseName, clearOutputDir),
00048       mNumberOfTimePoints(1u),
00049       mTimeStep(1.0)
00050 {
00051 }
00052 
00053 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00054 void XdmfMeshWriter<ELEMENT_DIM, SPACE_DIM>::WriteFilesUsingMesh(AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>& rMesh,
00055                                                                  bool keepOriginalElementIndexing)
00056 {
00057 #ifdef _MSC_VER
00058     EXCEPTION("XDMF is not supported under Windows at present.");
00059 #else
00060     assert(keepOriginalElementIndexing);
00061     this->mpDistributedMesh = dynamic_cast<DistributedTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* >(&rMesh);
00062     bool mesh_is_distributed = (this->mpDistributedMesh != NULL) && PetscTools::IsParallel();
00063 
00064     if (PetscTools::AmMaster())
00065     {
00066         // Write main test Grid collection (to be later replaced by temporal collection)
00067         // Write references to geometry and topology chunk(s)
00068         unsigned num_chunks = 1;
00069         if (mesh_is_distributed)
00070         {
00071             num_chunks = PetscTools::GetNumProcs();
00072         }
00073         WriteXdmfMasterFile(num_chunks);
00074     }
00075     if (!mesh_is_distributed && !PetscTools::AmMaster())
00076     {
00077         //If the mesh is not distributed then the master knows everything and will write the geometry/topology as a single chunk
00078         PetscTools::Barrier("XdmfMeshWriter wait for chunks to be written");
00079         return;
00080     }
00081 
00082     // Geometry
00083     std::stringstream local_geometry_file_name;
00084     local_geometry_file_name << this->mBaseName << "_geometry_"<< PetscTools::GetMyRank() <<".xml";
00085     out_stream geometry_file = this->mpOutputFileHandler->OpenOutputFile(local_geometry_file_name.str());
00086     std::string geom_type = "XYZ";
00087     if (SPACE_DIM == 2)
00088     {
00089         geom_type = "XY";
00090     }
00091     (*geometry_file) << "<Geometry GeometryType=\""<< geom_type <<"\">\n";
00092     unsigned num_nodes = rMesh.GetNumNodes();
00093     if (this->mpDistributedMesh)
00094     {
00095         num_nodes = this->mpDistributedMesh->GetNumLocalNodes() + this->mpDistributedMesh->GetNumHaloNodes();
00096     }
00097 
00098     (*geometry_file) << "\t<DataItem Format=\"XML\" Dimensions=\""<< num_nodes <<" "<< SPACE_DIM <<"\" DataType=\"Float\">";
00099 
00100     //  Map a global node index into a local index (into mNodes and mHaloNodes as if they were concatenated)
00101     std::map<unsigned, unsigned> global_to_node_index_map;
00102 
00103     //Node index that we are writing to the chunk (index into mNodes and mHaloNodes as if they were concatenated)
00104     unsigned index = 0;
00105 
00106     // Owned nodes come first
00107     for (typename AbstractMesh<ELEMENT_DIM,SPACE_DIM>::NodeIterator iter = rMesh.GetNodeIteratorBegin();
00108          iter != rMesh.GetNodeIteratorEnd();
00109          ++iter)
00110     {
00111         global_to_node_index_map[iter->GetIndex()] = index;
00112         index++;
00113         (*geometry_file) << "\n\t\t";
00114         c_vector<double, SPACE_DIM> current_item = (iter)->rGetLocation();
00115         for (unsigned j=0; j<SPACE_DIM; j++)
00116         {
00117             (*geometry_file) << current_item[j] << "\t";
00118         }
00119     }
00120 
00121     // Halo nodes
00122     if (this->mpDistributedMesh)
00123     {
00124         for (typename DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::HaloNodeIterator halo_iter=this->mpDistributedMesh->GetHaloNodeIteratorBegin();
00125                 halo_iter != this->mpDistributedMesh->GetHaloNodeIteratorEnd();
00126                 ++halo_iter)
00127         {
00128             global_to_node_index_map[(*halo_iter)->GetIndex()] = index;
00129             index++;
00130             (*geometry_file) << "\n\t\t";
00131             c_vector<double, SPACE_DIM> current_item = (*halo_iter)->rGetLocation();
00132             for (unsigned j=0; j<SPACE_DIM; j++)
00133             {
00134                 (*geometry_file) << current_item[j] << "\t";
00135             }
00136         }
00137     }
00138     (*geometry_file) << "\n";
00139 
00140     (*geometry_file) << "\t</DataItem>\n";
00141     (*geometry_file) << "</Geometry>\n";
00142     (*geometry_file) << "<!-- " + ChasteBuildInfo::GetProvenanceString() + "-->\n";
00143     geometry_file->close();
00144 
00145     // Topology
00146     std::stringstream local_topology_file_name;
00147     local_topology_file_name << this->mBaseName << "_topology_"<< PetscTools::GetMyRank() <<".xml";
00148     out_stream topology_file = this->mpOutputFileHandler->OpenOutputFile(local_topology_file_name.str());
00149     std::string top_type = "Tetrahedron";
00150     if (SPACE_DIM == 2)
00151     {
00152         top_type = "Triangle";
00153     }
00154     unsigned num_elems = rMesh.GetNumElements();
00155     if (this->mpDistributedMesh)
00156     {
00157         num_elems = this->mpDistributedMesh->GetNumLocalElements();
00158     }
00159     (*topology_file) << "<Topology TopologyType=\""<< top_type <<"\" NumberOfElements=\""<< num_elems <<"\">\n";
00160     (*topology_file) << "\t<DataItem Format=\"XML\" Dimensions=\""<< num_elems <<" "<< ELEMENT_DIM+1 <<"\">";
00161     for (typename AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>::ElementIterator elem_iter = rMesh.GetElementIteratorBegin();
00162          elem_iter != rMesh.GetElementIteratorEnd();
00163          ++elem_iter)
00164     {
00165         (*topology_file) << "\n\t\t";
00166         for (unsigned j=0; j<ELEMENT_DIM+1; j++)
00167         {
00168             unsigned local_index = global_to_node_index_map[ elem_iter->GetNodeGlobalIndex(j) ];
00169             (*topology_file) << local_index <<"\t";
00170         }
00171     }
00172     (*topology_file) << "\n";
00173 
00174     (*topology_file) << "\t</DataItem>\n";
00175     (*topology_file) << "</Topology>\n";
00176     (*topology_file) << "<!-- " + ChasteBuildInfo::GetProvenanceString() + "-->\n";
00177     topology_file->close();
00178     PetscTools::Barrier("XdmfMeshWriter wait for chunks to be written");
00179 #endif
00180 }
00181 
00182 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00183 void XdmfMeshWriter<ELEMENT_DIM, SPACE_DIM>::WriteFiles()
00184 {
00185 #ifdef _MSC_VER
00186     EXCEPTION("XDMF is not supported under Windows at present.");
00187 #else
00188     // This method is only called when there is no mesh.  We are writing from a reader.
00189     if (PetscTools::AmMaster())
00190     {
00191         WriteXdmfMasterFile();
00192 
00193         // Geometry
00194         out_stream geometry_file = this->mpOutputFileHandler->OpenOutputFile(this->mBaseName + "_geometry_0.xml");
00195         std::string geom_type = "XYZ";
00196         if (SPACE_DIM == 2)
00197         {
00198             geom_type = "XY";
00199         }
00200         (*geometry_file) << "<Geometry GeometryType=\""<< geom_type <<"\">\n";
00201         (*geometry_file) << "\t<DataItem Format=\"XML\" Dimensions=\""<< this->GetNumNodes() <<" "<< SPACE_DIM <<"\" DataType=\"Float\">";
00202         for (unsigned item_num=0; item_num<this->GetNumNodes(); item_num++)
00203         {
00204             (*geometry_file) << "\n\t\t";
00205             std::vector<double> current_item = this->GetNextNode();
00206             for (unsigned j=0; j<SPACE_DIM; j++)
00207             {
00208                 (*geometry_file) << current_item[j]<<"\t";
00209             }
00210         }
00211         (*geometry_file) << "\n";
00212 
00213         (*geometry_file) << "\t</DataItem>\n";
00214         (*geometry_file) << "</Geometry>\n";
00215         (*geometry_file) << "<!-- " + ChasteBuildInfo::GetProvenanceString() + "-->\n";
00216         geometry_file->close();
00217 
00218         // Topology
00219         out_stream topology_file = this->mpOutputFileHandler->OpenOutputFile(this->mBaseName + "_topology_0.xml");
00220         std::string top_type = "Tetrahedron";
00221         if (SPACE_DIM == 2)
00222         {
00223             top_type = "Triangle";
00224         }
00225         (*topology_file) << "<Topology TopologyType=\""<< top_type <<"\" NumberOfElements=\""<< this->GetNumElements() <<"\">\n";
00226         (*topology_file) << "\t<DataItem Format=\"XML\" Dimensions=\""<< this->GetNumElements() <<" "<< ELEMENT_DIM+1 <<"\">";
00227         for (unsigned item_num=0; item_num<this->GetNumElements(); item_num++)
00228         {
00229             (*topology_file) << "\n\t\t";
00230             std::vector<unsigned> current_item = this->GetNextElement().NodeIndices;
00231             for (unsigned j=0; j<ELEMENT_DIM+1; j++)
00232             {
00233                 (*topology_file) << current_item[j]<<"\t";
00234             }
00235         }
00236         (*topology_file) << "\n";
00237 
00238         (*topology_file) << "\t</DataItem>\n";
00239         (*topology_file) << "</Topology>\n";
00240         (*topology_file) << "<!-- " + ChasteBuildInfo::GetProvenanceString() + "-->\n";
00241         topology_file->close();
00242     }
00243 #endif
00244 }
00245 
00246 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00247 void XdmfMeshWriter<ELEMENT_DIM, SPACE_DIM>::WriteXdmfMasterFile(unsigned numberOfChunks)
00248 {
00249 #ifndef _MSC_VER
00250     assert(PetscTools::AmMaster());
00251     // Define namespace symbols
00252     XERCES_CPP_NAMESPACE_USE
00253 
00254     // Initialize Xerces.
00255     XMLPlatformUtils::Initialize();
00256 
00257     DOMImplementation* p_DOM_implementation = DOMImplementationRegistry::getDOMImplementation(X("core"));
00258 
00259     DOMDocumentType* p_DOM_document_type = p_DOM_implementation->createDocumentType(X("Xdmf"),0,X("Xdmf.dtd"));
00260     DOMDocument* p_DOM_document = p_DOM_implementation->createDocument(0, X("Xdmf"), p_DOM_document_type);
00261     DOMElement* p_root_element = p_DOM_document->getDocumentElement();
00262     p_root_element->setAttribute(X("Version"), X("2.0"));
00263     p_root_element->setAttribute(X("xmlns:xi"), X("http://www.w3.org/2001/XInclude"));
00264 
00265     DOMElement* p_domain_element =  p_DOM_document->createElement(X("Domain"));
00266     p_root_element->appendChild(p_domain_element);
00267 
00268     // Temporal collection
00269     DOMElement* p_grid_temp_collection_element =  p_DOM_document->createElement(X("Grid"));
00270     p_grid_temp_collection_element->setAttribute(X("CollectionType"), X("Temporal"));
00271     p_grid_temp_collection_element->setAttribute(X("GridType"), X("Collection"));
00272     p_domain_element->appendChild(p_grid_temp_collection_element);
00273 
00274     // Time values
00275     DOMElement* p_time_element =  p_DOM_document->createElement(X("Time"));
00276     p_time_element->setAttribute(X("TimeType"), X("HyperSlab"));
00277     p_grid_temp_collection_element->appendChild(p_time_element);
00278 
00279     DOMElement* p_time_dataitem_element =  p_DOM_document->createElement(X("DataItem"));
00280     p_time_dataitem_element->setAttribute(X("Format"),X("XML"));
00281     p_time_dataitem_element->setAttribute(X("NumberType"),X("Float"));
00282     p_time_dataitem_element->setAttribute(X("Dimensions"),X("3"));
00283     p_time_element->appendChild(p_time_dataitem_element);
00284 
00285     std::stringstream time_stream;
00286     time_stream << "0.0 " << mTimeStep << " " << mNumberOfTimePoints;
00287     DOMText* p_time_text = p_DOM_document->createTextNode(X(time_stream.str()));
00288     p_time_dataitem_element->appendChild(p_time_text);
00289 
00290     for(unsigned t=0; t<mNumberOfTimePoints; ++t)
00291     {
00292         DOMElement* p_grid_collection_element =  p_DOM_document->createElement(X("Grid"));
00293         p_grid_collection_element->setAttribute(X("CollectionType"), X("Spatial"));
00294         p_grid_collection_element->setAttribute(X("GridType"), X("Collection"));
00295         //p_grid_collection_element->setAttribute(X("Name"), X("spatial_collection"));
00296         p_grid_temp_collection_element->appendChild(p_grid_collection_element);
00297 
00298         if (t==0)
00299         {
00300             for (unsigned chunk=0; chunk<numberOfChunks; chunk++)
00301             {
00302                 std::stringstream chunk_stream;
00303                 chunk_stream << chunk;
00304 
00305                 DOMElement* p_grid_element =  p_DOM_document->createElement(X("Grid"));
00306                 p_grid_element->setAttribute(X("GridType"), X("Uniform"));
00307                 p_grid_element->setAttribute(X("Name"), X("Chunk_" + chunk_stream.str()));
00308                 p_grid_collection_element->appendChild(p_grid_element);
00309 
00310                 //DOMElement* p_geom_element =  p_DOM_document->createElement(X("Geometry"));
00311                 //p_geom_element->setAttribute(X("Reference"),X("/Xdmf/Domain/Geometry[1]"));
00312                 DOMElement* p_geom_element =  p_DOM_document->createElement(X("xi:include"));
00313                 p_geom_element->setAttribute(X("href"), X(this->mBaseName+"_geometry_"+chunk_stream.str()+".xml"));
00314                 p_grid_element->appendChild(p_geom_element);
00315                 //DOMElement* p_topo_element =  p_DOM_document->createElement(X("Topology"));
00316                 //p_topo_element->setAttribute(X("Reference"),X("/Xdmf/Domain/Topology[1]"));
00317                 DOMElement* p_topo_element =  p_DOM_document->createElement(X("xi:include"));
00318                 p_topo_element->setAttribute(X("href"), X(this->mBaseName+"_topology_"+chunk_stream.str()+".xml"));
00319                 p_grid_element->appendChild(p_topo_element);
00320 
00321                 /*
00322                  * p_grid_element may now need an Attribute (node data). Call Annotate,
00323                  * which here does nothing, but in pde can be overloaded to print variables
00324                  */
00325                 AddDataOnNodes(p_grid_element, p_DOM_document, t);
00326             }
00327         }
00328         else // t>0
00329         {
00330             for (unsigned chunk=0; chunk<numberOfChunks; chunk++)
00331             {
00332                 std::stringstream chunk_stream;
00333                 chunk_stream << chunk;
00334 
00335                 DOMElement* p_grid_element =  p_DOM_document->createElement(X("Grid"));
00336                 p_grid_element->setAttribute(X("GridType"), X("Subset"));
00337                 p_grid_element->setAttribute(X("Section"), X("All"));
00338                 p_grid_collection_element->appendChild(p_grid_element);
00339 
00340                 /*
00341                  * p_grid_element may now need an Attribute (node data). Call Annotate,
00342                  * which here does nothing, but in pde can be overloaded to print variables
00343                  */
00344                 AddDataOnNodes(p_grid_element, p_DOM_document, t);
00345                 DOMElement* p_grid_ref_element =  p_DOM_document->createElement(X("Grid"));
00346                 p_grid_ref_element->setAttribute(X("GridType"), X("Uniform"));
00347                 p_grid_ref_element->setAttribute(X("Reference"), X("XML"));
00348                 //p_grid_ref_element->setAttribute(X("Name"), X("Chunk_" + chunk_stream.str()));
00349 
00350                 DOMText* p_ref_text = p_DOM_document->createTextNode(X("/Xdmf/Domain/Grid/Grid/Grid[@Name=\"Chunk_"+chunk_stream.str()+"\"]"));
00351                 p_grid_ref_element->appendChild(p_ref_text);
00352                 p_grid_element->appendChild(p_grid_ref_element);
00353             }
00354         }
00355     }
00356     // Create a Comment node, and then append this to the root element.
00357     DOMComment* p_provenance_comment = p_DOM_document->createComment(X(" "+ChasteBuildInfo::GetProvenanceString()));
00358     p_DOM_document->appendChild(p_provenance_comment);
00359 
00360     XMLFormatTarget* p_target = new LocalFileFormatTarget(X(this->mpOutputFileHandler->GetOutputDirectoryFullPath() + this->mBaseName+".xdmf"));
00361 
00362 #if _XERCES_VERSION >= 30000
00363     DOMLSSerializer *p_serializer = ((DOMImplementationLS*)p_DOM_implementation)->createLSSerializer();
00364     p_serializer->getDomConfig()->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true);
00365     DOMLSOutput *p_output = ((DOMImplementationLS*)p_DOM_implementation)->createLSOutput();
00366     p_output->setByteStream(p_target);
00367     p_serializer->write(p_DOM_document, p_output);
00368 #else
00369     DOMWriter* p_serializer = ((DOMImplementationLS*)p_DOM_implementation)->createDOMWriter();
00370     p_serializer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true);
00371     p_serializer->writeNode(p_target, *p_DOM_document);
00372 #endif
00373 
00374     // Cleanup
00375     p_serializer->release();
00376     p_DOM_document->release();
00377     delete p_target;
00378     XMLPlatformUtils::Terminate();
00379 #endif // _MSC_VER
00380 }
00381 
00383 // Explicit instantiation
00385 
00386 template class XdmfMeshWriter<1,1>;
00387 template class XdmfMeshWriter<1,2>;
00388 template class XdmfMeshWriter<1,3>;
00389 template class XdmfMeshWriter<2,2>; // Actually used
00390 template class XdmfMeshWriter<2,3>;
00391 template class XdmfMeshWriter<3,3>; // Actually used

Generated by  doxygen 1.6.2