TrianglesMeshWriter.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 "TrianglesMeshWriter.hpp"
00037 
00038 #include "AbstractTetrahedralMesh.hpp"
00039 #include "Version.hpp"
00040 
00041 #include <cassert>
00042 
00044 // Implementation
00046 
00047 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00048 TrianglesMeshWriter<ELEMENT_DIM, SPACE_DIM>::TrianglesMeshWriter(
00049     const std::string &rDirectory,
00050     const std::string &rBaseName,
00051     const bool clearOutputDir)
00052         : AbstractTetrahedralMeshWriter<ELEMENT_DIM, SPACE_DIM>(rDirectory, rBaseName, clearOutputDir)
00053 {
00054 }
00055 
00056 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00057 TrianglesMeshWriter<ELEMENT_DIM, SPACE_DIM>::~TrianglesMeshWriter()
00058 {
00059 }
00060 
00061 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00062 void TrianglesMeshWriter<ELEMENT_DIM, SPACE_DIM>::SetWriteFilesAsBinary()
00063 {
00064     this->mFilesAreBinary=true;
00065 }
00066 
00067 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00068 void TrianglesMeshWriter<ELEMENT_DIM, SPACE_DIM>::WriteFiles()
00069 {
00070     std::string comment = "#\n# " + ChasteBuildInfo::GetProvenanceString();
00071 //    PetscTools::Barrier("DodgyBarrierBeforeNODE");
00072     MeshEventHandler::BeginEvent(MeshEventHandler::NODE);
00073     // Write node file
00074     std::string node_file_name = this->mBaseName + ".node";
00075     out_stream p_node_file = this->mpOutputFileHandler->OpenOutputFile(node_file_name, std::ios::binary | std::ios::trunc);
00076 
00077     // Write the node header
00078     unsigned num_attr = 0;
00079 
00080     if (this->mpMesh && !this->mFilesAreBinary) 
00081     {
00082         // Assumes that all nodes have the same number of attributes as the first node in the mesh.
00083         num_attr = this->mpMesh->GetNumNodeAttributes();
00084     }
00086     unsigned max_bdy_marker = 0;
00087     unsigned num_nodes = this->GetNumNodes();
00088 
00089     *p_node_file << num_nodes << "\t";
00090     *p_node_file << SPACE_DIM << "\t";
00091     *p_node_file << num_attr << "\t";
00092     *p_node_file << max_bdy_marker;
00093     if (this->mFilesAreBinary)
00094     {
00095         *p_node_file << "\tBIN\n";
00096     }
00097     else
00098     {
00099         *p_node_file << "\n";
00100     }
00101 
00102     *p_node_file << std::setprecision(20);
00103 
00104     // Write each node's data
00105     for (unsigned item_num=0; item_num<num_nodes; item_num++)
00106     {
00107         if (this->mpMesh && !this->mFilesAreBinary && num_attr!=0) 
00108         {
00109 
00111             WriteItem(p_node_file, item_num, this->GetNextNode(), this->mpMesh->GetNode(item_num)->rGetNodeAttributes());
00112         }
00113         else
00114         {
00115             WriteItem(p_node_file, item_num, this->GetNextNode());
00116         }
00117     }
00118     *p_node_file << comment << "\n";
00119     p_node_file->close();
00120 //    PetscTools::Barrier("DodgyBarrierAfterNODE");
00121     MeshEventHandler::EndEvent(MeshEventHandler::NODE);
00122     MeshEventHandler::BeginEvent(MeshEventHandler::ELE);
00123     if (ELEMENT_DIM < SPACE_DIM)
00124     {
00125         WriteElementsAsFaces();
00126         WriteFacesAsEdges();
00127         return;
00128     }
00129 
00130     // Write element file
00131     std::string element_file_name = this->mBaseName + ".ele";
00132     out_stream p_element_file = this->mpOutputFileHandler->OpenOutputFile(element_file_name, std::ios::binary | std::ios::trunc);
00133 
00134     // Write the element header
00135     unsigned num_elements = this->GetNumElements();
00136     num_attr = 1u; // We have a single region code
00137 
00138     // The condition below allows the writer to cope with a NodesOnlyMesh
00139     if (num_elements == 0)
00140     {
00141         *p_element_file << 0 << "\t";
00142         *p_element_file << 0 << "\t";
00143         *p_element_file << 0;
00144         if (this->mFilesAreBinary)
00145         {
00146             *p_element_file << "\tBIN\n";
00147         }
00148         else
00149         {
00150             *p_element_file << "\n";
00151         }
00152         p_element_file->close();
00153     }
00154     else
00155     {
00156         ElementData element_data = this->GetNextElement();
00157 
00158         unsigned nodes_per_element = element_data.NodeIndices.size();
00159         if (nodes_per_element != ELEMENT_DIM+1)
00160         {
00161             // Check that this is a quadratic mesh
00162             assert(ELEMENT_DIM == SPACE_DIM);
00163             assert(nodes_per_element == (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2);
00164          }
00165 
00166         *p_element_file << num_elements << "\t";
00167         *p_element_file << nodes_per_element << "\t";
00168         *p_element_file << num_attr;
00169         if (this->mFilesAreBinary)
00170         {
00171             *p_element_file << "\tBIN\n";
00172         }
00173         else
00174         {
00175             *p_element_file << "\n";
00176         }
00177 
00178         // Write each element's data
00179         std::vector<double> attribute_values(1);
00180         for (unsigned item_num=0; item_num<num_elements; item_num++)
00181         {
00182             /*
00183              * If item_num==0 we will already have got the element above (in order to
00184              * get the number of nodes per element).
00185              */
00186             if (item_num > 0)
00187             {
00188                 element_data = this->GetNextElement();
00189             }
00190             attribute_values[0] =  element_data.AttributeValue;
00191             WriteItem(p_element_file, item_num, element_data.NodeIndices, attribute_values);
00192         }
00193         *p_element_file << comment << "\n";
00194         p_element_file->close();
00195     }
00196 //    PetscTools::Barrier("DodgyBarrierAfterELE");
00197     MeshEventHandler::EndEvent(MeshEventHandler::ELE);
00198     MeshEventHandler::BeginEvent(MeshEventHandler::FACE);
00199     // Write boundary face file
00200     std::string face_file_name = this->mBaseName;
00201 
00202     if (ELEMENT_DIM == 1)
00203     {
00204         // In 1-D there is no boundary file: it's trivial to calculate
00205         return;
00206     }
00207     else if (ELEMENT_DIM == 2)
00208     {
00209         face_file_name = face_file_name + ".edge";
00210     }
00211     else
00212     {
00213         face_file_name = face_file_name + ".face";
00214     }
00215     out_stream p_face_file = this->mpOutputFileHandler->OpenOutputFile(face_file_name, std::ios::binary | std::ios::trunc);
00216 
00217     // Write the boundary face header
00218     if (num_elements != 0)
00219     {
00220         unsigned num_faces = this->GetNumBoundaryFaces();
00221 
00222         *p_face_file << num_faces << "\t";
00224         *p_face_file << max_bdy_marker;
00225         if (this->mFilesAreBinary)
00226         {
00227             *p_face_file << "\tBIN\n";
00228         }
00229         else
00230         {
00231             *p_face_file << "\n";
00232         }
00233 
00234         // Write each face's data
00235         std::vector<double> default_marker(0);
00236         for (unsigned item_num=0; item_num<num_faces; item_num++)
00237         {
00238             ElementData face_data = this->GetNextBoundaryElement();
00239             WriteItem(p_face_file, item_num, face_data.NodeIndices, default_marker);
00240         }
00241         *p_face_file << comment << "\n";
00242         p_face_file->close();
00243 
00244         if (this->GetNumCableElements() > 0)
00245         {
00246             // Write cable element file
00247             std::string cable_element_file_name = this->mBaseName + ".cable";
00248             out_stream p_cable_element_file = this->mpOutputFileHandler->OpenOutputFile(cable_element_file_name, std::ios::binary | std::ios::trunc);
00249 
00250             // Write the cable element header
00251             unsigned num_cable_elements = this->GetNumCableElements();
00253             num_attr = 1u; // We have a single region code - which is actually a radius
00254 
00255             *p_cable_element_file << num_cable_elements << "\t";
00256             *p_cable_element_file << 2 << "\t";
00257             *p_cable_element_file << num_attr;
00258             if (this->mFilesAreBinary)
00259             {
00260                 *p_cable_element_file << "\tBIN\n";
00261             }
00262             else
00263             {
00264                 *p_cable_element_file << "\n";
00265             }
00266 
00267             // Write each element's data
00268             std::vector<double> attribute_values(1);
00269             for (unsigned item_num=0; item_num<num_cable_elements; item_num++)
00270             {
00271                 ElementData cable_element_data = this->GetNextCableElement();
00272                 attribute_values[0] = cable_element_data.AttributeValue;
00273                 WriteItem(p_cable_element_file, item_num, cable_element_data.NodeIndices, attribute_values);
00274             }
00275             *p_cable_element_file << comment;
00276             p_cable_element_file->close();
00277         }
00278     }
00279 //    PetscTools::Barrier("DodgyBarrierAfterFACE");
00280     MeshEventHandler::EndEvent(MeshEventHandler::FACE);
00281 
00282 }
00283 
00284 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00285 void TrianglesMeshWriter<ELEMENT_DIM, SPACE_DIM>::WriteElementsAsFaces()
00286 {
00287     std::string comment = "#\n# " + ChasteBuildInfo::GetProvenanceString();
00288 
00289     std::string element_file_name = this->mBaseName;
00290     if (ELEMENT_DIM == 1 && (SPACE_DIM == 2 || SPACE_DIM == 3))
00291     {
00292         element_file_name = element_file_name + ".edge";
00293     }
00294     else if (ELEMENT_DIM == 2 && SPACE_DIM == 3)
00295     {
00296         element_file_name = element_file_name + ".face";
00297     }
00298 
00299     out_stream p_element_file = this->mpOutputFileHandler->OpenOutputFile(element_file_name, std::ios::binary | std::ios::trunc);
00300 
00301     // Write the element header
00302     unsigned num_elements = this->GetNumElements();
00303     assert(SPACE_DIM != ELEMENT_DIM);
00304     unsigned num_attr = 1;
00305 
00306     *p_element_file << num_elements << "\t";
00307     //*p_element_file << nodes_per_element << "\t";
00308     *p_element_file << num_attr;
00309     if (this->mFilesAreBinary)
00310     {
00311         *p_element_file << "\tBIN\n";
00312     }
00313     else
00314     {
00315         *p_element_file << "\n";
00316     }
00317 
00318     // Write each element's data
00319     std::vector<double> attribute_values(1);
00320     for (unsigned item_num=0; item_num<num_elements; item_num++)
00321     {
00322         ElementData element_data = this->GetNextElement();
00323         attribute_values[0] =  element_data.AttributeValue;
00324         WriteItem(p_element_file, item_num, element_data.NodeIndices, attribute_values);
00325     }
00326 
00327     *p_element_file << comment << "\n";
00328     p_element_file->close();
00329 
00330 }
00331 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00332 void TrianglesMeshWriter<ELEMENT_DIM, SPACE_DIM>::WriteFacesAsEdges()
00333 {
00334     std::string comment = "#\n# " + ChasteBuildInfo::GetProvenanceString();
00335 
00336     if (ELEMENT_DIM == 1 && (SPACE_DIM == 2 || SPACE_DIM == 3))
00337     {
00338         return;
00339     }
00340 
00341     assert(SPACE_DIM == 3 && ELEMENT_DIM == 2);
00342 
00343     std::string face_file_name = this->mBaseName;
00344     face_file_name = face_file_name + ".edge";
00345 
00346     out_stream p_face_file = this->mpOutputFileHandler->OpenOutputFile(face_file_name, std::ios::binary | std::ios::trunc);
00347 
00348     // Write the boundary face header
00349     unsigned num_faces = this->GetNumBoundaryFaces();
00350 
00351     unsigned max_bdy_marker = 0;
00352     std::vector<double> default_marker(0);
00353 
00354     *p_face_file << num_faces << "\t";
00355     *p_face_file << max_bdy_marker;
00356     if (this->mFilesAreBinary)
00357     {
00358         *p_face_file << "\tBIN\n";
00359     }
00360     else
00361     {
00362         *p_face_file << "\n";
00363     }
00364 
00365     // Write each face's data
00366     for (unsigned item_num=0; item_num<num_faces; item_num++)
00367     {
00368         ElementData face_data = this->GetNextBoundaryElement();
00369         WriteItem(p_face_file, item_num, face_data.NodeIndices, default_marker);
00370     }
00371     *p_face_file << comment << "\n";
00372     p_face_file->close();
00373 }
00374 
00375 
00376 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00377 template<class T_DATA>
00378 void TrianglesMeshWriter<ELEMENT_DIM, SPACE_DIM>::WriteItem(out_stream &pFile, unsigned itemNumber,
00379                                                             const std::vector<T_DATA> &dataPacket)
00380 {
00381     //Writing with no attribute
00382     //Instantiates the attribute variety with the attributes empty
00383     WriteItem(pFile, itemNumber, dataPacket, std::vector<double>());
00384 }
00385 
00386 
00387 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00388 template<class T_DATA>
00389 void TrianglesMeshWriter<ELEMENT_DIM, SPACE_DIM>::WriteItem(out_stream &pFile, unsigned itemNumber,
00390                                                             const std::vector<T_DATA> &dataPacket,
00391                                                             const std::vector<double> &rAttributes)
00392 {
00393     if (this->mFilesAreBinary)
00394     {
00395         // No item numbers
00396         // Write raw data out of std::vector into the file
00397         pFile->write((char*)&dataPacket[0], dataPacket.size()*sizeof(T_DATA));
00398 
00399         // Write raw attribute(s)
00400         // MSVC 10 will trip an assertion on accessing the 0th element if the vector is empty.
00401         // Note that C++11 gives vectors a .data() method which would be a better way of doing this!
00402         if (!rAttributes.empty())
00403         {
00404             pFile->write((char*)&rAttributes[0], rAttributes.size()*sizeof(double));
00405         }
00406     }
00407     else
00408     {
00409         *pFile << itemNumber;
00410         for (unsigned i=0; i<dataPacket.size(); i++)
00411         {
00412             *pFile << "\t" << dataPacket[i];
00413         }
00414         for (unsigned i=0; i<rAttributes.size(); i++)
00415         {
00416             *pFile << "\t" << rAttributes[i];
00417         }
00418         *pFile << "\n";
00419     }
00420 }
00421 
00423 // Explicit instantiation
00425 
00426 template class TrianglesMeshWriter<1,1>;
00427 template class TrianglesMeshWriter<1,2>;
00428 template class TrianglesMeshWriter<1,3>;
00429 template class TrianglesMeshWriter<2,2>;
00430 template class TrianglesMeshWriter<2,3>;
00431 template class TrianglesMeshWriter<3,3>;
00432 
00437 template void TrianglesMeshWriter<1, 1>::WriteItem(out_stream &, unsigned, const std::vector<unsigned> &, const std::vector<double>   & );
00438 template void TrianglesMeshWriter<1, 1>::WriteItem(out_stream &, unsigned, const std::vector<double>   &, const std::vector<double>   & );
00439 template void TrianglesMeshWriter<1, 2>::WriteItem(out_stream &, unsigned, const std::vector<unsigned> &, const std::vector<double>   & );
00440 template void TrianglesMeshWriter<1, 2>::WriteItem(out_stream &, unsigned, const std::vector<double>   &, const std::vector<double>   & );
00441 template void TrianglesMeshWriter<1, 3>::WriteItem(out_stream &, unsigned, const std::vector<unsigned> &, const std::vector<double>   & );
00442 template void TrianglesMeshWriter<1, 3>::WriteItem(out_stream &, unsigned, const std::vector<double>   &, const std::vector<double>   & );
00443 template void TrianglesMeshWriter<2, 2>::WriteItem(out_stream &, unsigned, const std::vector<unsigned> &, const std::vector<double>   & );
00444 template void TrianglesMeshWriter<2, 2>::WriteItem(out_stream &, unsigned, const std::vector<double>   &, const std::vector<double>   & );
00445 template void TrianglesMeshWriter<2, 3>::WriteItem(out_stream &, unsigned, const std::vector<unsigned> &, const std::vector<double>   & );
00446 template void TrianglesMeshWriter<2, 3>::WriteItem(out_stream &, unsigned, const std::vector<double>   &, const std::vector<double>   & );
00447 template void TrianglesMeshWriter<3, 3>::WriteItem(out_stream &, unsigned, const std::vector<unsigned> &, const std::vector<double>   & );
00448 template void TrianglesMeshWriter<3, 3>::WriteItem(out_stream &, unsigned, const std::vector<double>   &, const std::vector<double>   & );

Generated by  doxygen 1.6.2