Chaste Release::3.1
|
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 #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<ELEMENT_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 for (unsigned i=0; i<ELEMENT_DIM; i++) 00315 { 00316 *p_node_file << r_current_item[i] << "\t"; 00317 } 00318 00319 *p_node_file << "\n"; 00320 } 00321 p_node_file->close(); 00322 00323 //Now Element files 00324 00325 std::vector<boost::shared_ptr<std::ofstream> > elem_files = OpenElementFiles(true); 00326 typedef typename AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>::ElementIterator ElemIterType; 00327 00328 for (ElemIterType iter = this->mpDistributedMesh->GetElementIteratorBegin(); 00329 iter != this->mpDistributedMesh->GetElementIteratorEnd(); 00330 ++iter) 00331 { 00332 if ( this->mpDistributedMesh->CalculateDesignatedOwnershipOfElement(iter->GetIndex())) 00333 { 00334 assert(iter->GetUnsignedAttribute() < mRegionNames.size());//segfault guard 00335 00336 *elem_files[iter->GetUnsignedAttribute()] << "Element:\t" << iter->GetIndex()+1 << " 0 0 Nodes:\t"; 00337 for (unsigned i=0; i<this->mNodesPerElement; i++) 00338 { 00339 *elem_files[iter->GetUnsignedAttribute()] << iter->GetNodeGlobalIndex(i)+1 << "\t"; 00340 } 00341 00342 *elem_files[iter->GetUnsignedAttribute()] << "\n"; 00343 } 00344 } 00345 00346 for (unsigned region_index=0; region_index<mRegionNames.size(); region_index++) 00347 { 00348 elem_files[region_index]->close(); 00349 } 00350 00351 } 00352 00353 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00354 void CmguiMeshWriter<ELEMENT_DIM, SPACE_DIM>::WriteFilesFooter() 00355 { 00356 //No need of footers here, but void implementation is needed 00357 } 00358 00359 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00360 std::ios_base::openmode CmguiMeshWriter<ELEMENT_DIM, SPACE_DIM>::GetOpenMode(bool append) 00361 { 00362 std::ios_base::openmode mode = std::ios::out; 00363 if (append) 00364 { 00365 mode |= std::ios::app; // Note: bitwise OR operation 00366 } 00367 else 00368 { 00369 mode |= std::ios::trunc; 00370 } 00371 return mode; 00372 } 00373 00375 // Explicit instantiation 00377 00378 template class CmguiMeshWriter<1,1>; 00379 template class CmguiMeshWriter<1,2>; 00380 template class CmguiMeshWriter<1,3>; 00381 template class CmguiMeshWriter<2,2>; 00382 template class CmguiMeshWriter<2,3>; 00383 template class CmguiMeshWriter<3,3>;