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 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>;