Chaste Release::3.1
VertexMeshWriter.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 "VertexMeshWriter.hpp"
00037 #include "Version.hpp"
00038 
00042 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00043 struct MeshWriterIterators
00044 {
00046     typename AbstractMesh<ELEMENT_DIM,SPACE_DIM>::NodeIterator* pNodeIter;
00048     typename VertexMesh<ELEMENT_DIM,SPACE_DIM>::VertexElementIterator* pElemIter;
00049 };
00050 
00052 // Implementation
00054 
00055 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00056 VertexMeshWriter<ELEMENT_DIM, SPACE_DIM>::VertexMeshWriter(const std::string& rDirectory,
00057                                                            const std::string& rBaseName,
00058                                                            const bool clearOutputDir)
00059     : AbstractMeshWriter<ELEMENT_DIM, SPACE_DIM>(rDirectory, rBaseName, clearOutputDir),
00060       mpMesh(NULL),
00061       mpIters(new MeshWriterIterators<ELEMENT_DIM, SPACE_DIM>),
00062       mpNodeMap(NULL),
00063       mNodeMapCurrentIndex(0)
00064 {
00065     mpIters->pNodeIter = NULL;
00066     mpIters->pElemIter = NULL;
00067 
00068 #ifdef CHASTE_VTK
00069      // Dubious, since we shouldn't yet know what any details of the mesh are.
00070      mpVtkUnstructedMesh = vtkUnstructuredGrid::New();
00071 #endif //CHASTE_VTK
00072 }
00073 
00074 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00075 VertexMeshWriter<ELEMENT_DIM, SPACE_DIM>::~VertexMeshWriter()
00076 {
00077     if (mpIters->pNodeIter)
00078     {
00079         delete mpIters->pNodeIter;
00080         delete mpIters->pElemIter;
00081     }
00082 
00083     delete mpIters;
00084 
00085     if (mpNodeMap)
00086     {
00087         delete mpNodeMap;
00088     }
00089 
00090 #ifdef CHASTE_VTK
00091      // Dubious, since we shouldn't yet know what any details of the mesh are.
00092      mpVtkUnstructedMesh->Delete(); // Reference counted
00093 #endif //CHASTE_VTK
00094 }
00095 
00096 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00097 std::vector<double> VertexMeshWriter<ELEMENT_DIM, SPACE_DIM>::GetNextNode()
00098 {
00099     if (mpMesh)
00100     {
00101         // Sanity check
00102         assert(this->mNumNodes == mpMesh->GetNumNodes());
00103 
00104         std::vector<double> coordinates(SPACE_DIM+1);
00105 
00106         // Get the node coordinates using the node iterator (thus skipping deleted nodes)
00107         for (unsigned j=0; j<SPACE_DIM; j++)
00108         {
00109             coordinates[j] = (*(mpIters->pNodeIter))->GetPoint()[j];
00110         }
00111         coordinates[SPACE_DIM] = (*(mpIters->pNodeIter))->IsBoundaryNode();
00112 
00113         ++(*(mpIters->pNodeIter));
00114 
00115         return coordinates;
00116     }
00117     else
00118     {
00119         return AbstractMeshWriter<ELEMENT_DIM,SPACE_DIM>::GetNextNode();
00120     }
00121 }
00122 
00123 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00124 VertexElementData VertexMeshWriter<ELEMENT_DIM, SPACE_DIM>::GetNextElementWithFaces()
00125 {
00126     // This method should only be called in 3D
00127     assert(SPACE_DIM == 3);
00128     assert(mpMesh);
00129     assert(this->mNumElements == mpMesh->GetNumElements());
00130 
00131     // Create data structure for this element
00132     VertexElementData elem_data;
00133 
00134     // Store node indices owned by this element
00135     elem_data.NodeIndices.resize((*(mpIters->pElemIter))->GetNumNodes());
00136     for (unsigned j=0; j<elem_data.NodeIndices.size(); j++)
00137     {
00138         unsigned old_index = (*(mpIters->pElemIter))->GetNodeGlobalIndex(j);
00139         elem_data.NodeIndices[j] = mpMesh->IsMeshChanging() ? mpNodeMap->GetNewIndex(old_index) : old_index;
00140     }
00141 
00142     // Store faces owned by this element
00143     elem_data.Faces.resize((*(mpIters->pElemIter))->GetNumFaces());
00144     for (unsigned i=0; i<elem_data.Faces.size(); i++)
00145     {
00146         // Get pointer to this face
00147         VertexElement<ELEMENT_DIM-1, SPACE_DIM>* p_face = (*(mpIters->pElemIter))->GetFace(i);
00148 
00149         // Create data structure for this face
00150         ElementData face_data;
00151 
00152         // Store this face's index
00153         face_data.AttributeValue = p_face->GetIndex();
00154 
00155         // Store node indices owned by this face
00156         face_data.NodeIndices.resize(p_face->GetNumNodes());
00157         for (unsigned j=0; j<face_data.NodeIndices.size(); j++)
00158         {
00159             unsigned old_index = p_face->GetNodeGlobalIndex(j);
00160             face_data.NodeIndices[j] = mpMesh->IsMeshChanging() ? mpNodeMap->GetNewIndex(old_index) : old_index;
00161         }
00162 
00163         // Store this face
00164         elem_data.Faces[i] = face_data;
00165 
00167     }
00168 
00169     // Set attribute
00170     elem_data.AttributeValue = (*(mpIters->pElemIter))->GetAttribute();
00171     ++(*(mpIters->pElemIter));
00172 
00173     return elem_data;
00174 }
00175 
00176 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00177 ElementData VertexMeshWriter<ELEMENT_DIM, SPACE_DIM>::GetNextElement()
00178 {
00180 
00181     if (mpMesh)
00182     {
00183         assert(this->mNumElements == mpMesh->GetNumElements());
00184 
00185         ElementData elem_data;
00186         elem_data.NodeIndices.resize((*(mpIters->pElemIter))->GetNumNodes());
00187         for (unsigned j=0; j<elem_data.NodeIndices.size(); j++)
00188         {
00189             unsigned old_index = (*(mpIters->pElemIter))->GetNodeGlobalIndex(j);
00190             elem_data.NodeIndices[j] = mpMesh->IsMeshChanging() ? mpNodeMap->GetNewIndex(old_index) : old_index;
00191         }
00192 
00193         // Set attribute
00194         elem_data.AttributeValue = (*(mpIters->pElemIter))->GetAttribute();
00195         ++(*(mpIters->pElemIter));
00196 
00197         return elem_data;
00198     }
00199     else
00200     {
00201         return AbstractMeshWriter<ELEMENT_DIM, SPACE_DIM>::GetNextElement();
00202     }
00203 }
00204 
00205 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00206 void VertexMeshWriter<ELEMENT_DIM, SPACE_DIM>::WriteVtkUsingMesh(VertexMesh<ELEMENT_DIM, SPACE_DIM>& rMesh, std::string stamp)
00207 {
00208 #ifdef CHASTE_VTK
00209     //Make the Vtk mesh
00210     assert(SPACE_DIM==3 || SPACE_DIM == 2);
00211     vtkPoints* p_pts = vtkPoints::New(VTK_DOUBLE);
00212     p_pts->GetData()->SetName("Vertex positions");
00213     for (unsigned node_num=0; node_num<rMesh.GetNumNodes(); node_num++)
00214     {
00215         c_vector<double, SPACE_DIM> position = rMesh.GetNode(node_num)->rGetLocation();
00216         if (SPACE_DIM==2)
00217         {
00218             p_pts->InsertPoint(node_num, position[0], position[1], 0.0);
00219         }
00220         else
00221         {
00222             p_pts->InsertPoint(node_num, position[0], position[1], position[2]);
00223         }
00224     }
00225 
00226     mpVtkUnstructedMesh->SetPoints(p_pts);
00227     p_pts->Delete(); // Reference counted
00228     for (typename VertexMesh<ELEMENT_DIM,SPACE_DIM>::VertexElementIterator iter = rMesh.GetElementIteratorBegin();
00229          iter != rMesh.GetElementIteratorEnd();
00230          ++iter)
00231     {
00232         vtkCell* p_cell;
00233         if (SPACE_DIM == 2)
00234         {
00235             p_cell = vtkPolygon::New();
00236         }
00237         else
00238         {
00239             p_cell = vtkConvexPointSet::New();
00240         }
00241         vtkIdList* p_cell_id_list = p_cell->GetPointIds();
00242         p_cell_id_list->SetNumberOfIds(iter->GetNumNodes());
00243         for (unsigned j = 0; j < iter->GetNumNodes(); ++j)
00244         {
00245             p_cell_id_list->SetId(j, iter->GetNodeGlobalIndex(j));
00246         }
00247         mpVtkUnstructedMesh->InsertNextCell(p_cell->GetCellType(), p_cell_id_list);
00248         p_cell->Delete(); //Reference counted
00249     }
00250 
00251     // Vtk mesh is now made
00252     assert(mpVtkUnstructedMesh->CheckAttributes() == 0);
00253     vtkXMLUnstructuredGridWriter* p_writer = vtkXMLUnstructuredGridWriter::New();
00254     p_writer->SetInput(mpVtkUnstructedMesh);
00255     // Uninitialised stuff arises (see #1079), but you can remove valgrind problems by removing compression:
00256     // **** REMOVE WITH CAUTION *****
00257     p_writer->SetCompressor(NULL);
00258     // **** REMOVE WITH CAUTION *****
00259 
00260     std::string vtk_file_name = this->mpOutputFileHandler->GetOutputDirectoryFullPath() + this->mBaseName;
00261     if (stamp != "")
00262     {
00263         vtk_file_name += "_" + stamp;
00264     }
00265     vtk_file_name += ".vtu";
00266 
00267     p_writer->SetFileName(vtk_file_name.c_str());
00268     //p_writer->PrintSelf(std::cout, vtkIndent());
00269     p_writer->Write();
00270     p_writer->Delete(); // Reference counted
00271 #endif //CHASTE_VTK
00272 }
00273 
00274 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00275 void VertexMeshWriter<ELEMENT_DIM, SPACE_DIM>::AddCellData(std::string dataName, std::vector<double> dataPayload)
00276 {
00277 #ifdef CHASTE_VTK
00278     vtkDoubleArray* p_scalars = vtkDoubleArray::New();
00279     p_scalars->SetName(dataName.c_str());
00280     for (unsigned i=0; i<dataPayload.size(); i++)
00281     {
00282         p_scalars->InsertNextValue(dataPayload[i]);
00283     }
00284 
00285     vtkCellData* p_cell_data = mpVtkUnstructedMesh->GetCellData();
00286     p_cell_data->AddArray(p_scalars);
00287     p_scalars->Delete(); // Reference counted
00288 #endif //CHASTE_VTK
00289 }
00290 
00291 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00292 void VertexMeshWriter<ELEMENT_DIM, SPACE_DIM>::AddPointData(std::string dataName, std::vector<double> dataPayload)
00293 {
00294 #ifdef CHASTE_VTK
00295     vtkDoubleArray* p_scalars = vtkDoubleArray::New();
00296     p_scalars->SetName(dataName.c_str());
00297     for (unsigned i=0; i<dataPayload.size(); i++)
00298     {
00299         p_scalars->InsertNextValue(dataPayload[i]);
00300     }
00301 
00302     vtkPointData* p_point_data = mpVtkUnstructedMesh->GetPointData();
00303     p_point_data->AddArray(p_scalars);
00304     p_scalars->Delete(); // Reference counted
00305 #endif //CHASTE_VTK
00306 }
00307 
00309 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00310 void VertexMeshWriter<ELEMENT_DIM, SPACE_DIM>::WriteFilesUsingMesh(VertexMesh<ELEMENT_DIM,SPACE_DIM>& rMesh)
00311 {
00312 
00313     this->mpMeshReader = NULL;
00314     mpMesh = &rMesh;
00315 
00316     this->mNumNodes = mpMesh->GetNumNodes();
00317     this->mNumElements = mpMesh->GetNumElements();
00318 
00319     typedef typename AbstractMesh<ELEMENT_DIM,SPACE_DIM>::NodeIterator NodeIterType;
00320     mpIters->pNodeIter = new NodeIterType(mpMesh->GetNodeIteratorBegin());
00321 
00322     typedef typename VertexMesh<ELEMENT_DIM,SPACE_DIM>::VertexElementIterator ElemIterType;
00323     mpIters->pElemIter = new ElemIterType(mpMesh->GetElementIteratorBegin());
00324 
00325     // Set up node map if we might have deleted nodes
00326     mNodeMapCurrentIndex = 0;
00327     if (mpMesh->IsMeshChanging())
00328     {
00329         mpNodeMap = new NodeMap(mpMesh->GetNumAllNodes());
00330         for (NodeIterType it = mpMesh->GetNodeIteratorBegin(); it != mpMesh->GetNodeIteratorEnd(); ++it)
00331         {
00332             mpNodeMap->SetNewIndex(it->GetIndex(), mNodeMapCurrentIndex++);
00333         }
00334     }
00335     WriteFiles();
00336 }
00337 
00338 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00339 void VertexMeshWriter<ELEMENT_DIM, SPACE_DIM>::WriteFiles()
00340 {
00341     std::string comment = "# " + ChasteBuildInfo::GetProvenanceString();
00342 
00343     // Write node file
00344     std::string node_file_name = this->mBaseName + ".node";
00345     out_stream p_node_file = this->mpOutputFileHandler->OpenOutputFile(node_file_name);
00346 
00347     // Write the node header
00348     unsigned num_attr = 0;
00349     unsigned max_bdy_marker = 1; // as we include boundary node information in the node file
00350     unsigned num_nodes = this->GetNumNodes();
00351 
00352     *p_node_file << num_nodes << "\t";
00353     *p_node_file << SPACE_DIM << "\t";
00354     *p_node_file << num_attr << "\t";
00355     *p_node_file << max_bdy_marker << "\n";
00356     *p_node_file << std::setprecision(6);
00357 
00358     // Write each node's data
00359     for (unsigned item_num=0; item_num<num_nodes; item_num++)
00360     {
00361         std::vector<double> current_item = this->GetNextNode();
00362         *p_node_file << item_num;
00363         for (unsigned i=0; i<SPACE_DIM+1; i++)
00364         {
00365             *p_node_file << "\t" << current_item[i];
00366         }
00367         *p_node_file << "\n";
00368     }
00369     *p_node_file << comment << "\n";
00370     p_node_file->close();
00371 
00372     // Write element file
00373     std::string element_file_name = this->mBaseName + ".cell";
00374     out_stream p_element_file = this->mpOutputFileHandler->OpenOutputFile(element_file_name);
00375 
00376     // Write the element header
00377     unsigned num_elements = this->GetNumElements();
00378 
00380     double first_elem_attribute_value = (*(mpIters->pElemIter))->GetAttribute();
00381     if (first_elem_attribute_value != 0)
00382     {
00383         num_attr = 1;
00384     }
00385 
00386     *p_element_file << num_elements << "\t";
00387     *p_element_file << num_attr << "\n";
00388 
00389     // Write each element's data
00390     for (unsigned item_num=0; item_num<num_elements; item_num++)
00391     {
00392         if (SPACE_DIM == 2) // In 2D, write the node indices owned by this element
00393         {
00394             // Get data for this element
00395             ElementData elem_data = this->GetNextElement();
00396 
00397             // Get the node indices owned by this element
00398             std::vector<unsigned> node_indices = elem_data.NodeIndices;
00399 
00400             // Write this element's index and the number of nodes owned by it to file
00401             *p_element_file << item_num <<  "\t" << node_indices.size();
00402 
00403             // Write the node indices owned by this element to file
00404             for (unsigned i=0; i<node_indices.size(); i++)
00405             {
00406                 *p_element_file << "\t" << node_indices[i];
00407             }
00408 
00409             // Write the element attribute
00410             if (elem_data.AttributeValue != 0)
00411             {
00412                 *p_element_file << "\t" << elem_data.AttributeValue;
00413             }
00414 
00415             // New line
00416             *p_element_file << "\n";
00417         }
00418         else // 3D
00419         {
00420             assert(SPACE_DIM == 3);
00421 
00422             // Get data for this element
00423             VertexElementData elem_data_with_faces = this->GetNextElementWithFaces();
00424 
00425             // Get the node indices owned by this element
00426             std::vector<unsigned> node_indices = elem_data_with_faces.NodeIndices;
00427 
00428             // Write this element's index and the number of nodes owned by it to file
00429             *p_element_file << item_num <<  "\t" << node_indices.size();
00430 
00431             // Write the node indices owned by this element to file
00432             for (unsigned i=0; i<node_indices.size(); i++)
00433             {
00434                 *p_element_file << "\t" << node_indices[i];
00435             }
00436 
00437             // Get the faces owned by this element (if any)
00438             std::vector<ElementData> faces = elem_data_with_faces.Faces;
00439 
00440             // Write the number of faces owned by this element to file
00441             *p_element_file << "\t" << faces.size();
00442 
00443             for (unsigned j=0; j<faces.size(); j++)
00444             {
00445                 // Get the node indices owned by this face
00446                 std::vector<unsigned> face_node_indices = faces[j].NodeIndices;
00447 
00448                 // Write this face's index and the number of nodes owned by it to file
00449                 *p_element_file << "\t" << faces[j].AttributeValue <<  "\t" << face_node_indices.size();
00450 
00451                 // Write the node indices owned by this element to file
00452                 for (unsigned i=0; i<face_node_indices.size(); i++)
00453                 {
00454                     *p_element_file << "\t" << face_node_indices[i];
00455                 }
00456 
00458             }
00459 
00460             // Write the element attribute if necessary
00461             if (elem_data_with_faces.AttributeValue != 0)
00462             {
00463                 *p_element_file << "\t" << elem_data_with_faces.AttributeValue;
00464             }
00465 
00466             // New line
00467             *p_element_file << "\n";
00468         }
00469     }
00470 
00471     *p_element_file << comment << "\n";
00472     p_element_file->close();
00473 }
00474 
00476 // Explicit instantiation
00478 
00479 template class VertexMeshWriter<1,1>;
00480 template class VertexMeshWriter<1,2>;
00481 template class VertexMeshWriter<1,3>;
00482 template class VertexMeshWriter<2,2>;
00483 template class VertexMeshWriter<2,3>;
00484 template class VertexMeshWriter<3,3>;