PottsMeshWriter.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 "PottsMeshWriter.hpp"
00037 #include "Version.hpp"
00038 
00042 template<unsigned SPACE_DIM>
00043 struct MeshPottsWriterIterators
00044 {
00046     typename AbstractMesh<SPACE_DIM,SPACE_DIM>::NodeIterator* pNodeIter;
00048     typename PottsMesh<SPACE_DIM>::PottsElementIterator* pElemIter;
00049 };
00050 
00052 // Implementation
00054 
00055 template<unsigned SPACE_DIM>
00056 PottsMeshWriter<SPACE_DIM>::PottsMeshWriter(const std::string& rDirectory,
00057                                                            const std::string& rBaseName,
00058                                                            const bool clearOutputDir)
00059     : AbstractMeshWriter<SPACE_DIM, SPACE_DIM>(rDirectory, rBaseName, clearOutputDir),
00060       mpMesh(NULL),
00061       mpIters(new MeshPottsWriterIterators<SPACE_DIM>),
00062       mpNodeMap(NULL),
00063       mNodeMapCurrentIndex(0)
00064 {
00065     mpIters->pNodeIter = NULL;
00066     mpIters->pElemIter = NULL;
00067 }
00068 
00069 template<unsigned SPACE_DIM>
00070 PottsMeshWriter<SPACE_DIM>::~PottsMeshWriter()
00071 {
00072     if (mpIters->pNodeIter)
00073     {
00074         delete mpIters->pNodeIter;
00075         delete mpIters->pElemIter;
00076     }
00077 
00078     delete mpIters;
00079 
00080     if (mpNodeMap)
00081     {
00082         delete mpNodeMap;
00083     }
00084 }
00085 
00086 template<unsigned SPACE_DIM>
00087 std::vector<double> PottsMeshWriter<SPACE_DIM>::GetNextNode()
00088 {
00089     if (mpMesh)
00090     {
00091         // Sanity check
00092         assert(this->mNumNodes == mpMesh->GetNumNodes());
00093 
00094         std::vector<double> coordinates(SPACE_DIM+1);
00095 
00096         // Get the node coordinates using the node iterator (thus skipping deleted nodes)
00097         for (unsigned j=0; j<SPACE_DIM; j++)
00098         {
00099             coordinates[j] = (*(mpIters->pNodeIter))->GetPoint()[j];
00100         }
00101         coordinates[SPACE_DIM] = (*(mpIters->pNodeIter))->IsBoundaryNode();
00102 
00103         ++(*(mpIters->pNodeIter));
00104 
00105         return coordinates;
00106     }
00107     else
00108     {
00109         return AbstractMeshWriter<SPACE_DIM,SPACE_DIM>::GetNextNode();
00110     }
00111 }
00112 
00113 template<unsigned SPACE_DIM>
00114 ElementData PottsMeshWriter<SPACE_DIM>::GetNextElement()
00115 {
00116     if (mpMesh)
00117     {
00118         assert(this->mNumElements == mpMesh->GetNumElements());
00119 
00120         ElementData elem_data;
00121         elem_data.NodeIndices.resize((*(mpIters->pElemIter))->GetNumNodes());
00122         for (unsigned j=0; j<elem_data.NodeIndices.size(); j++)
00123         {
00124             unsigned old_index = (*(mpIters->pElemIter))->GetNodeGlobalIndex(j);
00125             elem_data.NodeIndices[j] = mpMesh->IsMeshChanging() ? mpNodeMap->GetNewIndex(old_index) : old_index;
00126         }
00127 
00128         // Set attribute
00129         elem_data.AttributeValue = (*(mpIters->pElemIter))->GetAttribute();
00130         ++(*(mpIters->pElemIter));
00131 
00132         return elem_data;
00133     }
00134     else
00135     {
00136         return AbstractMeshWriter<SPACE_DIM, SPACE_DIM>::GetNextElement();
00137     }
00138 }
00139 
00141 template<unsigned SPACE_DIM>
00142 void PottsMeshWriter<SPACE_DIM>::WriteFilesUsingMesh(PottsMesh<SPACE_DIM>& rMesh)
00143 {
00144     this->mpMeshReader = NULL;
00145     mpMesh = &rMesh;
00146 
00147     this->mNumNodes = mpMesh->GetNumNodes();
00148     this->mNumElements = mpMesh->GetNumElements();
00149 
00150     typedef typename AbstractMesh<SPACE_DIM,SPACE_DIM>::NodeIterator NodeIterType;
00151     mpIters->pNodeIter = new NodeIterType(mpMesh->GetNodeIteratorBegin());
00152 
00153     typedef typename PottsMesh<SPACE_DIM>::PottsElementIterator ElemIterType;
00154     mpIters->pElemIter = new ElemIterType(mpMesh->GetElementIteratorBegin());
00155 
00156     // Set up node map if we might have deleted nodes
00157     mNodeMapCurrentIndex = 0;
00158     if (mpMesh->IsMeshChanging())
00159     {
00160         mpNodeMap = new NodeMap(mpMesh->GetNumAllNodes());
00161         for (NodeIterType it = mpMesh->GetNodeIteratorBegin(); it != mpMesh->GetNodeIteratorEnd(); ++it)
00162         {
00163             mpNodeMap->SetNewIndex(it->GetIndex(), mNodeMapCurrentIndex++);
00164         }
00165     }
00166 
00167     WriteFiles();
00168 }
00169 
00170 template<unsigned SPACE_DIM>
00171 void PottsMeshWriter<SPACE_DIM>::WriteFiles()
00172 {
00173     std::string comment = "# " + ChasteBuildInfo::GetProvenanceString();
00174 
00175     // Write node file
00176     std::string node_file_name = this->mBaseName + ".node";
00177     out_stream p_node_file = this->mpOutputFileHandler->OpenOutputFile(node_file_name);
00178 
00179     // Write the node header
00180     unsigned num_attr = 0;
00181     unsigned max_bdy_marker = 1; // as we include boundary node information in the node file
00182     unsigned num_nodes = this->GetNumNodes();
00183 
00184     *p_node_file << num_nodes << "\t";
00185     *p_node_file << SPACE_DIM << "\t";
00186     *p_node_file << num_attr << "\t";
00187     *p_node_file << max_bdy_marker << "\n";
00188     *p_node_file << std::setprecision(6);
00189 
00190     // Write each node's data
00191     for (unsigned item_num=0; item_num<num_nodes; item_num++)
00192     {
00193         std::vector<double> current_item = this->GetNextNode();
00194         *p_node_file << item_num;
00195         for (unsigned i=0; i<SPACE_DIM+1; i++)
00196         {
00197             *p_node_file << "\t" << current_item[i];
00198         }
00199         *p_node_file << "\n";
00200     }
00201     *p_node_file << comment << "\n";
00202     p_node_file->close();
00203 
00204     // Write element file
00205     std::string element_file_name = this->mBaseName + ".cell";
00206     out_stream p_element_file = this->mpOutputFileHandler->OpenOutputFile(element_file_name);
00207 
00208     // Write the element header
00209     unsigned num_elements = this->GetNumElements();
00210     *p_element_file << num_elements << "\t";
00211     num_attr = 1; // Always write attributes by default
00212     /*
00213      * Note that in contrast to other mesh classes, it is perfectly reasonable for
00214      * a PottsMesh to have no elements, particularly in when it is being used in
00215      * the context of a CaBasedCellPopulation.
00216      */
00217     if (num_elements != 0)
00218     {
00219         *p_element_file << num_attr << "\n";
00220     }
00221     else
00222     {
00223         *p_element_file << 0 << "\n";
00224     }
00225 
00226     // Write each element's data
00227     for (unsigned item_num=0; item_num<num_elements; item_num++)
00228     {
00229         // Get data for this element
00230         ElementData elem_data = this->GetNextElement();
00231 
00232         // Get the node indices owned by this element
00233         std::vector<unsigned> node_indices = elem_data.NodeIndices;
00234 
00235         // Write this element's index and the number of nodes owned by it to file
00236         *p_element_file << item_num <<  "\t" << node_indices.size();
00237 
00238         // Write the node indices owned by this element to file
00239         for (unsigned i=0; i<node_indices.size(); i++)
00240         {
00241             *p_element_file << "\t" << node_indices[i];
00242         }
00243 
00244         // Write the element attribute
00245         *p_element_file << "\t" << elem_data.AttributeValue;
00246 
00247         // New line
00248         *p_element_file << "\n";
00249     }
00250 
00251     *p_element_file << comment << "\n";
00252     p_element_file->close();
00253 }
00254 
00256 // Explicit instantiation
00258 
00259 template class PottsMeshWriter<1>;
00260 template class PottsMeshWriter<2>;
00261 template class PottsMeshWriter<3>;

Generated by  doxygen 1.6.2