CmguiMeshWriter.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 #include "Exception.hpp"
00036 #include "CmguiMeshWriter.hpp"
00037 #include "Version.hpp"
00038 #include <boost/shared_ptr.hpp>
00039 
00040 #include "AbstractTetrahedralMesh.hpp"
00041 #include "DistributedTetrahedralMesh.hpp"
00042 
00044 // Implementation
00046 
00047 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00048 CmguiMeshWriter<ELEMENT_DIM,SPACE_DIM>::CmguiMeshWriter(const std::string &rDirectory,
00049                                                         const std::string &rBaseName,
00050                                                         bool cleanDirectory)
00051         : AbstractTetrahedralMeshWriter<ELEMENT_DIM,SPACE_DIM>(rDirectory, rBaseName, cleanDirectory)
00052 {
00053     this->mIndexFromZero = false;
00054     mGroupName = this->mBaseName;
00055 
00056     switch (ELEMENT_DIM)
00057     {
00058         case 1:
00059         {
00060             mElementFileHeader = CmguiElementFileHeader1D;
00061             mCoordinatesFileHeader = CmguiCoordinatesFileHeader1D;
00062             mAdditionalFieldHeader = CmguiAdditionalFieldHeader1D;
00063             break;
00064         }
00065         case 2:
00066         {
00067             mElementFileHeader = CmguiElementFileHeader2D;
00068             mCoordinatesFileHeader = CmguiCoordinatesFileHeader2D;
00069             mAdditionalFieldHeader = CmguiAdditionalFieldHeader2D;
00070             break;
00071         }
00072         case 3:
00073         {
00074             mElementFileHeader = CmguiElementFileHeader3D;
00075             mCoordinatesFileHeader = CmguiCoordinatesFileHeader3D;
00076             mAdditionalFieldHeader = CmguiAdditionalFieldHeader3D;
00077             break;
00078         }
00079         default:
00080         {
00081             NEVER_REACHED;
00082         }
00083     }
00084 
00085 
00086     mNumNodesPerElement = ELEMENT_DIM+1;
00087     mReordering.resize(mNumNodesPerElement);
00088     for (unsigned i=0; i<mNumNodesPerElement; i++)
00089     {
00090         mReordering[i] = i;
00091     }
00092 }
00093 
00094 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00095 void CmguiMeshWriter<ELEMENT_DIM,SPACE_DIM>::WriteFiles()
00096 {
00098     // Write the exnode file
00100     out_stream p_node_file = OpenNodeFile();
00101     WriteNodeFileHeader(p_node_file);
00102 
00103     // Write each node's data
00104     for (unsigned item_num=0; item_num<this->GetNumNodes(); item_num++)
00105     {
00106         std::vector<double> current_item = this->GetNextNode();
00107 
00108         *p_node_file << "Node:\t" << item_num+1 << "\t";
00109         for (unsigned i=0; i<SPACE_DIM; i++)
00110         {
00111             *p_node_file << current_item[i] << "\t";
00112         }
00113 
00114         *p_node_file << "\n";
00115     }
00116     p_node_file->close();
00117 
00119     // Write the exlem file
00121 
00122     std::vector<boost::shared_ptr<std::ofstream> > elem_files = OpenElementFiles();
00123     WriteElementsFileHeader(elem_files);
00124 
00125     // Write each elements's data
00126     for (unsigned item_num=0; item_num<this->GetNumElements(); item_num++)
00127     {
00128         ElementData elem =this->GetNextElement();
00129         std::vector<unsigned> current_element = elem.NodeIndices;
00130 
00132         assert(elem.AttributeValue < mRegionNames.size());
00133 
00134         *elem_files[elem.AttributeValue] << "Element:\t" << item_num+1 << " 0 0 Nodes:\t";
00135         for (unsigned i=0; i<mNumNodesPerElement; i++)
00136         {
00137             *elem_files[elem.AttributeValue] << current_element[mReordering[i]]+1 << "\t";
00138         }
00139 
00140         *elem_files[elem.AttributeValue] << "\n";
00141 
00142     }
00143 
00144     for (unsigned region_index=0; region_index<mRegionNames.size(); region_index++)
00145     {
00146         elem_files[region_index]->close();
00147     }
00148 }
00149 
00150 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00151 void CmguiMeshWriter<ELEMENT_DIM,SPACE_DIM>::SetAdditionalFieldNames(std::vector<std::string>& rFieldNames)
00152 {
00153     mAdditionalFieldNames = rFieldNames;
00154 }
00155 
00156 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00157 void CmguiMeshWriter<ELEMENT_DIM,SPACE_DIM>::SetRegionNames(std::vector<std::string>& rRegionNames)
00158 {
00159     mRegionNames = rRegionNames;
00160 }
00161 
00162 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00163 out_stream CmguiMeshWriter<ELEMENT_DIM, SPACE_DIM>::OpenNodeFile(bool append)
00164 {
00165     std::string node_file_name = this->mBaseName + ".exnode";
00166     return this->mpOutputFileHandler->OpenOutputFile(node_file_name, GetOpenMode(append));
00167 }
00168 
00169 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00170 std::vector<boost::shared_ptr<std::ofstream> > CmguiMeshWriter<ELEMENT_DIM, SPACE_DIM>::OpenElementFiles(bool append)
00171 {
00172 
00173     std::vector<boost::shared_ptr<std::ofstream> > elem_files;
00174     // If nobody defined region names we default to the same name as the file name.
00175     if (mRegionNames.size() == 0)
00176     {
00177        mRegionNames.push_back(this->mBaseName);
00178     }
00179     elem_files.resize(mRegionNames.size());
00180 
00181     std::string directory = this->mpOutputFileHandler->GetOutputDirectoryFullPath();
00182     for (unsigned region_index=0; region_index<mRegionNames.size(); region_index++)
00183     {
00184         std::string elem_file_name = mRegionNames[region_index] + ".exelem";
00185 
00186         boost::shared_ptr<std::ofstream> p_output_file(new std::ofstream((directory+elem_file_name).c_str(), GetOpenMode(append)));
00187 #define COVERAGE_IGNORE
00188         if (!p_output_file->is_open())
00189         {
00190             EXCEPTION("Could not open file \"" + elem_file_name + "\" in " + directory);
00191         }
00192 #undef COVERAGE_IGNORE
00193 
00194         // NOTE THAT one could simply do:
00195         //
00196         // elem_files[region_index]  = this->mpOutputFileHandler->OpenOutputFile(elem_file_name, GetOpenMode(append));
00197         //
00198         // but that implies automatic conversion between std::auto_ptr to boost::shared_ptr.
00199         // That is OK with most compilers, but the combination of gcc 4.1 and boost 1.33 complains about that
00200         elem_files[region_index]  = p_output_file;
00201     }
00202     return elem_files;
00203 }
00204 
00205 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00206 void CmguiMeshWriter<ELEMENT_DIM,SPACE_DIM>::WriteNodeFileHeader(out_stream& rpNodeFile)
00207 {
00208     // Write provenance info
00209     std::string comment = "! " + ChasteBuildInfo::GetProvenanceString();
00210     *rpNodeFile << comment;
00211 
00212     // Write the node header
00213     *rpNodeFile << "Group name: " << this->mGroupName << "\n";
00214     switch (SPACE_DIM)
00215     {
00216         case 1:
00217         {
00218             *rpNodeFile << CmguiNodeFileHeader1D;
00219             break;
00220         }
00221         case 2:
00222         {
00223             *rpNodeFile << CmguiNodeFileHeader2D;
00224             break;
00225         }
00226         case 3:
00227         {
00228             *rpNodeFile << CmguiNodeFileHeader3D;
00229             break;
00230         }
00231         default:
00232         {
00233             NEVER_REACHED;
00234         }
00235     }
00236 }
00237 
00238 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00239 void CmguiMeshWriter<ELEMENT_DIM,SPACE_DIM>::WriteElementsFileHeader(std::vector<boost::shared_ptr<std::ofstream> >& rElemFiles)
00240 {
00241 
00242        for (unsigned region_index=0; region_index<mRegionNames.size(); region_index++)
00243        {
00244            // Write the elem header
00245 
00246            //write provenance info
00247            std::string comment = "! " + ChasteBuildInfo::GetProvenanceString();
00248            *rElemFiles[region_index] << comment;
00249 
00250            *rElemFiles[region_index] << "Group name: " << mGroupName << "\n";
00251            *rElemFiles[region_index] << mElementFileHeader;
00252 
00253            // Now we need to figure out how many additional fields we have
00254            unsigned number_of_fields = mAdditionalFieldNames.size();
00255            std::stringstream string_of_number_of_fields;
00256 
00257            // We write the number of additional fields + 1 because the coordinates field gets written anyway...
00258            string_of_number_of_fields << number_of_fields+1;
00259 
00260            // ...and write accordingly the total number of fields
00261            *rElemFiles[region_index] << " #Fields="<<string_of_number_of_fields.str()<<"\n";
00262 
00263            // First field (the coordinates field is fixed and alwys there)
00264            *rElemFiles[region_index] << mCoordinatesFileHeader;
00265 
00266            // Now write the specification for each additional field
00267            for (unsigned i = 0; i <  number_of_fields; i++)
00268            {
00269                //unsigned to string
00270                std::stringstream i_string;
00271                i_string << i+2;
00272                *rElemFiles[region_index]<<i_string.str()<<")  "<<mAdditionalFieldNames[i]<<" ,";
00273                *rElemFiles[region_index] << mAdditionalFieldHeader;
00274            }
00275        }
00276 }
00277 
00278 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00279 void CmguiMeshWriter<ELEMENT_DIM, SPACE_DIM>::CreateFilesWithHeaders()
00280 {
00281     /*
00282      *  Node file
00283      */
00284     out_stream p_node_file = OpenNodeFile();
00285     WriteNodeFileHeader(p_node_file);
00286     p_node_file->close();
00287 
00288     /*
00289      *  Element files
00290      */
00291      // Array with file descriptors for each of regions
00292      std::vector<boost::shared_ptr<std::ofstream> > elem_files = OpenElementFiles();
00293      WriteElementsFileHeader(elem_files);
00294      for (unsigned i = 0; i < elem_files.size(); i++)
00295      {
00296          elem_files[i]->close();
00297      }
00298 }
00299 
00300 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00301 void CmguiMeshWriter<ELEMENT_DIM, SPACE_DIM>::AppendLocalDataToFiles()
00302 {
00303     //Nodes first
00304     out_stream p_node_file = OpenNodeFile(true);
00305 
00306     typedef typename AbstractMesh<ELEMENT_DIM,SPACE_DIM>::NodeIterator NodeIterType;
00307 
00308     for (NodeIterType iter = this->mpDistributedMesh->GetNodeIteratorBegin();
00309          iter != this->mpDistributedMesh->GetNodeIteratorEnd();
00310          ++iter)
00311     {
00312         const c_vector<double, SPACE_DIM>& r_current_item = iter->rGetLocation();
00313         *p_node_file << "Node:\t" << iter->GetIndex()+1 << "\t";
00314 
00315         for (unsigned i=0; i<SPACE_DIM; i++)
00316         {
00317             *p_node_file << r_current_item[i] << "\t";
00318         }
00319 
00320         *p_node_file << "\n";
00321     }
00322     p_node_file->close();
00323 
00324     //Now Element files
00325 
00326     std::vector<boost::shared_ptr<std::ofstream> > elem_files = OpenElementFiles(true);
00327     typedef typename AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>::ElementIterator ElemIterType;
00328 
00329     for (ElemIterType iter = this->mpDistributedMesh->GetElementIteratorBegin();
00330          iter != this->mpDistributedMesh->GetElementIteratorEnd();
00331          ++iter)
00332     {
00333         if ( this->mpDistributedMesh->CalculateDesignatedOwnershipOfElement(iter->GetIndex()))
00334         {
00335             assert(iter->GetUnsignedAttribute() < mRegionNames.size());//segfault guard
00336 
00337             *elem_files[iter->GetUnsignedAttribute()] << "Element:\t" << iter->GetIndex()+1 << " 0 0 Nodes:\t";
00338             for (unsigned i=0; i<this->mNodesPerElement; i++)
00339             {
00340                 *elem_files[iter->GetUnsignedAttribute()]  << iter->GetNodeGlobalIndex(i)+1 << "\t";
00341             }
00342 
00343             *elem_files[iter->GetUnsignedAttribute()] << "\n";
00344         }
00345     }
00346 
00347     for (unsigned region_index=0; region_index<mRegionNames.size(); region_index++)
00348     {
00349         elem_files[region_index]->close();
00350     }
00351 
00352 }
00353 
00354 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00355 void CmguiMeshWriter<ELEMENT_DIM, SPACE_DIM>::WriteFilesFooter()
00356 {
00357     //No need of footers here, but void implementation is needed
00358 }
00359 
00360 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00361 std::ios_base::openmode CmguiMeshWriter<ELEMENT_DIM, SPACE_DIM>::GetOpenMode(bool append)
00362 {
00363     std::ios_base::openmode mode = std::ios::out;
00364     if (append)
00365     {
00366         mode |= std::ios::app; // Note: bitwise OR operation
00367     }
00368     else
00369     {
00370         mode |= std::ios::trunc;
00371     }
00372     return mode;
00373 }
00374 
00376 // Explicit instantiation
00378 
00379 template class CmguiMeshWriter<1,1>;
00380 template class CmguiMeshWriter<1,2>;
00381 template class CmguiMeshWriter<1,3>;
00382 template class CmguiMeshWriter<2,2>;
00383 template class CmguiMeshWriter<2,3>;
00384 template class CmguiMeshWriter<3,3>;

Generated by  doxygen 1.6.2