VertexMeshWriter.cpp

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