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