00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "VertexMeshWriter.hpp"
00037 #include "Version.hpp"
00038 #include "Cylindrical2dVertexMesh.hpp"
00039 #include "Toroidal2dVertexMesh.hpp"
00040
00044 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00045 struct MeshWriterIterators
00046 {
00048 typename AbstractMesh<ELEMENT_DIM,SPACE_DIM>::NodeIterator* pNodeIter;
00050 typename VertexMesh<ELEMENT_DIM,SPACE_DIM>::VertexElementIterator* pElemIter;
00051 };
00052
00054
00056
00057 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00058 VertexMeshWriter<ELEMENT_DIM, SPACE_DIM>::VertexMeshWriter(const std::string& rDirectory,
00059 const std::string& rBaseName,
00060 const bool clearOutputDir)
00061 : AbstractMeshWriter<ELEMENT_DIM, SPACE_DIM>(rDirectory, rBaseName, clearOutputDir),
00062 mpMesh(NULL),
00063 mpIters(new MeshWriterIterators<ELEMENT_DIM, SPACE_DIM>),
00064 mpNodeMap(NULL),
00065 mNodeMapCurrentIndex(0)
00066 {
00067 mpIters->pNodeIter = NULL;
00068 mpIters->pElemIter = NULL;
00069
00070 #ifdef CHASTE_VTK
00071
00072 mpVtkUnstructedMesh = vtkUnstructuredGrid::New();
00073 #endif //CHASTE_VTK
00074 }
00075
00076 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00077 VertexMeshWriter<ELEMENT_DIM, SPACE_DIM>::~VertexMeshWriter()
00078 {
00079 if (mpIters->pNodeIter)
00080 {
00081 delete mpIters->pNodeIter;
00082 delete mpIters->pElemIter;
00083 }
00084
00085 delete mpIters;
00086
00087 if (mpNodeMap)
00088 {
00089 delete mpNodeMap;
00090 }
00091
00092 #ifdef CHASTE_VTK
00093
00094 mpVtkUnstructedMesh->Delete();
00095 #endif //CHASTE_VTK
00096 }
00097
00098 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00099 std::vector<double> VertexMeshWriter<ELEMENT_DIM, SPACE_DIM>::GetNextNode()
00100 {
00101 if (mpMesh)
00102 {
00103
00104 assert(this->mNumNodes == mpMesh->GetNumNodes());
00105
00106 std::vector<double> coordinates(SPACE_DIM+1);
00107
00108
00109 for (unsigned j=0; j<SPACE_DIM; j++)
00110 {
00111 coordinates[j] = (*(mpIters->pNodeIter))->GetPoint()[j];
00112 }
00113 coordinates[SPACE_DIM] = (*(mpIters->pNodeIter))->IsBoundaryNode();
00114
00115 ++(*(mpIters->pNodeIter));
00116
00117 return coordinates;
00118 }
00119 else
00120 {
00121 return AbstractMeshWriter<ELEMENT_DIM,SPACE_DIM>::GetNextNode();
00122 }
00123 }
00124
00125 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00126 VertexElementData VertexMeshWriter<ELEMENT_DIM, SPACE_DIM>::GetNextElementWithFaces()
00127 {
00128
00129 assert(SPACE_DIM == 3);
00130 assert(mpMesh);
00131 assert(this->mNumElements == mpMesh->GetNumElements());
00132
00133
00134 VertexElementData elem_data;
00135
00136
00137 elem_data.NodeIndices.resize((*(mpIters->pElemIter))->GetNumNodes());
00138 for (unsigned j=0; j<elem_data.NodeIndices.size(); j++)
00139 {
00140 unsigned old_index = (*(mpIters->pElemIter))->GetNodeGlobalIndex(j);
00141 elem_data.NodeIndices[j] = mpMesh->IsMeshChanging() ? mpNodeMap->GetNewIndex(old_index) : old_index;
00142 }
00143
00144
00145 elem_data.Faces.resize((*(mpIters->pElemIter))->GetNumFaces());
00146 for (unsigned i=0; i<elem_data.Faces.size(); i++)
00147 {
00148
00149 VertexElement<ELEMENT_DIM-1, SPACE_DIM>* p_face = (*(mpIters->pElemIter))->GetFace(i);
00150
00151
00152 ElementData face_data;
00153
00154
00155 face_data.AttributeValue = p_face->GetIndex();
00156
00157
00158 face_data.NodeIndices.resize(p_face->GetNumNodes());
00159 for (unsigned j=0; j<face_data.NodeIndices.size(); j++)
00160 {
00161 unsigned old_index = p_face->GetNodeGlobalIndex(j);
00162 face_data.NodeIndices[j] = mpMesh->IsMeshChanging() ? mpNodeMap->GetNewIndex(old_index) : old_index;
00163 }
00164
00165
00166 elem_data.Faces[i] = face_data;
00167
00169 }
00170
00171
00172 elem_data.AttributeValue = (unsigned)(*(mpIters->pElemIter))->GetAttribute();
00173 ++(*(mpIters->pElemIter));
00174
00175 return elem_data;
00176 }
00177
00178 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00179 ElementData VertexMeshWriter<ELEMENT_DIM, SPACE_DIM>::GetNextElement()
00180 {
00182
00183 if (mpMesh)
00184 {
00185 assert(this->mNumElements == mpMesh->GetNumElements());
00186
00187 ElementData elem_data;
00188 elem_data.NodeIndices.resize((*(mpIters->pElemIter))->GetNumNodes());
00189 for (unsigned j=0; j<elem_data.NodeIndices.size(); j++)
00190 {
00191 unsigned old_index = (*(mpIters->pElemIter))->GetNodeGlobalIndex(j);
00192 elem_data.NodeIndices[j] = mpMesh->IsMeshChanging() ? mpNodeMap->GetNewIndex(old_index) : old_index;
00193 }
00194
00195
00196 elem_data.AttributeValue = (*(mpIters->pElemIter))->GetAttribute();
00197 ++(*(mpIters->pElemIter));
00198
00199 return elem_data;
00200 }
00201 else
00202 {
00203 return AbstractMeshWriter<ELEMENT_DIM, SPACE_DIM>::GetNextElement();
00204 }
00205 }
00206
00207 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00208 void VertexMeshWriter<ELEMENT_DIM, SPACE_DIM>::WriteVtkUsingMesh(VertexMesh<ELEMENT_DIM, SPACE_DIM>& rMesh, std::string stamp)
00209 {
00210 #ifdef CHASTE_VTK
00211 assert(SPACE_DIM==3 || SPACE_DIM == 2);
00212
00213
00214 MakeVtkMesh(rMesh);
00215
00216
00217 assert(mpVtkUnstructedMesh->CheckAttributes() == 0);
00218 vtkXMLUnstructuredGridWriter* p_writer = vtkXMLUnstructuredGridWriter::New();
00219 #if VTK_MAJOR_VERSION >= 6
00220 p_writer->SetInputData(mpVtkUnstructedMesh);
00221 #else
00222 p_writer->SetInput(mpVtkUnstructedMesh);
00223 #endif
00224
00225
00226 p_writer->SetCompressor(NULL);
00227
00228
00229 std::string vtk_file_name = this->mpOutputFileHandler->GetOutputDirectoryFullPath() + this->mBaseName;
00230 if (stamp != "")
00231 {
00232 vtk_file_name += "_" + stamp;
00233 }
00234 vtk_file_name += ".vtu";
00235
00236 p_writer->SetFileName(vtk_file_name.c_str());
00237
00238 p_writer->Write();
00239 p_writer->Delete();
00240 #endif //CHASTE_VTK
00241 }
00242
00249 template<>
00250 void VertexMeshWriter<2, 2>::WriteVtkUsingMesh(VertexMesh<2, 2>& rMesh, std::string stamp)
00251 {
00252 #ifdef CHASTE_VTK
00253
00254 if (dynamic_cast<Toroidal2dVertexMesh*>(&rMesh))
00255 {
00256 MutableVertexMesh<2, 2>* p_mesh_for_vtk = static_cast<Toroidal2dVertexMesh*>(&rMesh)->GetMeshForVtk();
00257 MakeVtkMesh(*p_mesh_for_vtk);
00258
00259
00260 delete p_mesh_for_vtk;
00261 }
00262 else if (dynamic_cast<Cylindrical2dVertexMesh*>(&rMesh))
00263 {
00264 MutableVertexMesh<2, 2>* p_mesh_for_vtk = static_cast<Cylindrical2dVertexMesh*>(&rMesh)->GetMeshForVtk();
00265 MakeVtkMesh(*p_mesh_for_vtk);
00266
00267
00268 delete p_mesh_for_vtk;
00269 }
00270 else
00271 {
00272 MakeVtkMesh(rMesh);
00273 }
00274
00275
00276 assert(mpVtkUnstructedMesh->CheckAttributes() == 0);
00277 vtkXMLUnstructuredGridWriter* p_writer = vtkXMLUnstructuredGridWriter::New();
00278 #if VTK_MAJOR_VERSION >= 6
00279 p_writer->SetInputData(mpVtkUnstructedMesh);
00280 #else
00281 p_writer->SetInput(mpVtkUnstructedMesh);
00282 #endif
00283
00284
00285 p_writer->SetCompressor(NULL);
00286
00287
00288 std::string vtk_file_name = this->mpOutputFileHandler->GetOutputDirectoryFullPath() + this->mBaseName;
00289 if (stamp != "")
00290 {
00291 vtk_file_name += "_" + stamp;
00292 }
00293 vtk_file_name += ".vtu";
00294
00295 p_writer->SetFileName(vtk_file_name.c_str());
00296
00297 p_writer->Write();
00298 p_writer->Delete();
00299 #endif //CHASTE_VTK
00300 }
00301
00302 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00303 void VertexMeshWriter<ELEMENT_DIM, SPACE_DIM>::MakeVtkMesh(VertexMesh<ELEMENT_DIM, SPACE_DIM>& rMesh)
00304 {
00305 #ifdef CHASTE_VTK
00306
00307 vtkPoints* p_pts = vtkPoints::New(VTK_DOUBLE);
00308 p_pts->GetData()->SetName("Vertex positions");
00309 for (unsigned node_num=0; node_num<rMesh.GetNumNodes(); node_num++)
00310 {
00311 c_vector<double, SPACE_DIM> position = rMesh.GetNode(node_num)->rGetLocation();
00312 if (SPACE_DIM==2)
00313 {
00314 p_pts->InsertPoint(node_num, position[0], position[1], 0.0);
00315 }
00316 else
00317 {
00318 p_pts->InsertPoint(node_num, position[0], position[1], position[2]);
00319 }
00320 }
00321
00322 mpVtkUnstructedMesh->SetPoints(p_pts);
00323 p_pts->Delete();
00324 for (typename VertexMesh<ELEMENT_DIM,SPACE_DIM>::VertexElementIterator iter = rMesh.GetElementIteratorBegin();
00325 iter != rMesh.GetElementIteratorEnd();
00326 ++iter)
00327 {
00328 vtkCell* p_cell;
00329 if (SPACE_DIM == 2)
00330 {
00331 p_cell = vtkPolygon::New();
00332 }
00333 else
00334 {
00335 p_cell = vtkConvexPointSet::New();
00336 }
00337 vtkIdList* p_cell_id_list = p_cell->GetPointIds();
00338 p_cell_id_list->SetNumberOfIds(iter->GetNumNodes());
00339 for (unsigned j=0; j<iter->GetNumNodes(); ++j)
00340 {
00341 p_cell_id_list->SetId(j, iter->GetNodeGlobalIndex(j));
00342 }
00343 mpVtkUnstructedMesh->InsertNextCell(p_cell->GetCellType(), p_cell_id_list);
00344 p_cell->Delete();
00345 }
00346 #endif //CHASTE_VTK
00347 }
00348
00349 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00350 void VertexMeshWriter<ELEMENT_DIM, SPACE_DIM>::AddCellData(std::string dataName, std::vector<double> dataPayload)
00351 {
00352 #ifdef CHASTE_VTK
00353 vtkDoubleArray* p_scalars = vtkDoubleArray::New();
00354 p_scalars->SetName(dataName.c_str());
00355 for (unsigned i=0; i<dataPayload.size(); i++)
00356 {
00357 p_scalars->InsertNextValue(dataPayload[i]);
00358 }
00359
00360 vtkCellData* p_cell_data = mpVtkUnstructedMesh->GetCellData();
00361 p_cell_data->AddArray(p_scalars);
00362 p_scalars->Delete();
00363 #endif //CHASTE_VTK
00364 }
00365
00366 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00367 void VertexMeshWriter<ELEMENT_DIM, SPACE_DIM>::AddPointData(std::string dataName, std::vector<double> dataPayload)
00368 {
00369 #ifdef CHASTE_VTK
00370 vtkDoubleArray* p_scalars = vtkDoubleArray::New();
00371 p_scalars->SetName(dataName.c_str());
00372 for (unsigned i=0; i<dataPayload.size(); i++)
00373 {
00374 p_scalars->InsertNextValue(dataPayload[i]);
00375 }
00376
00377 vtkPointData* p_point_data = mpVtkUnstructedMesh->GetPointData();
00378 p_point_data->AddArray(p_scalars);
00379 p_scalars->Delete();
00380 #endif //CHASTE_VTK
00381 }
00382
00384 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00385 void VertexMeshWriter<ELEMENT_DIM, SPACE_DIM>::WriteFilesUsingMesh(VertexMesh<ELEMENT_DIM,SPACE_DIM>& rMesh)
00386 {
00387 this->mpMeshReader = NULL;
00388 mpMesh = &rMesh;
00389
00390 this->mNumNodes = mpMesh->GetNumNodes();
00391 this->mNumElements = mpMesh->GetNumElements();
00392
00393 typedef typename AbstractMesh<ELEMENT_DIM,SPACE_DIM>::NodeIterator NodeIterType;
00394 mpIters->pNodeIter = new NodeIterType(mpMesh->GetNodeIteratorBegin());
00395
00396 typedef typename VertexMesh<ELEMENT_DIM,SPACE_DIM>::VertexElementIterator ElemIterType;
00397 mpIters->pElemIter = new ElemIterType(mpMesh->GetElementIteratorBegin());
00398
00399
00400 mNodeMapCurrentIndex = 0;
00401 if (mpMesh->IsMeshChanging())
00402 {
00403 mpNodeMap = new NodeMap(mpMesh->GetNumAllNodes());
00404 for (NodeIterType it = mpMesh->GetNodeIteratorBegin(); it != mpMesh->GetNodeIteratorEnd(); ++it)
00405 {
00406 mpNodeMap->SetNewIndex(it->GetIndex(), mNodeMapCurrentIndex++);
00407 }
00408 }
00409 WriteFiles();
00410 }
00411
00412 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00413 void VertexMeshWriter<ELEMENT_DIM, SPACE_DIM>::WriteFiles()
00414 {
00415 std::string comment = "# " + ChasteBuildInfo::GetProvenanceString();
00416
00417
00418 std::string node_file_name = this->mBaseName + ".node";
00419 out_stream p_node_file = this->mpOutputFileHandler->OpenOutputFile(node_file_name);
00420
00421
00422 unsigned num_attr = 0;
00423 unsigned max_bdy_marker = 1;
00424 unsigned num_nodes = this->GetNumNodes();
00425
00426 *p_node_file << num_nodes << "\t";
00427 *p_node_file << SPACE_DIM << "\t";
00428 *p_node_file << num_attr << "\t";
00429 *p_node_file << max_bdy_marker << "\n";
00430 *p_node_file << std::setprecision(6);
00431
00432
00433 for (unsigned item_num=0; item_num<num_nodes; item_num++)
00434 {
00435 std::vector<double> current_item = this->GetNextNode();
00436 *p_node_file << item_num;
00437 for (unsigned i=0; i<SPACE_DIM+1; i++)
00438 {
00439 *p_node_file << "\t" << current_item[i];
00440 }
00441 *p_node_file << "\n";
00442 }
00443 *p_node_file << comment << "\n";
00444 p_node_file->close();
00445
00446
00447 std::string element_file_name = this->mBaseName + ".cell";
00448 out_stream p_element_file = this->mpOutputFileHandler->OpenOutputFile(element_file_name);
00449
00450
00451 num_attr = 1;
00452 unsigned num_elements = this->GetNumElements();
00453 *p_element_file << num_elements << "\t" << num_attr << "\n";
00454
00455
00456 for (unsigned item_num=0; item_num<num_elements; item_num++)
00457 {
00458 if (SPACE_DIM == 2)
00459 {
00460
00461 ElementData elem_data = this->GetNextElement();
00462
00463
00464 std::vector<unsigned> node_indices = elem_data.NodeIndices;
00465
00466
00467 *p_element_file << item_num << "\t" << node_indices.size();
00468
00469
00470 for (unsigned i=0; i<node_indices.size(); i++)
00471 {
00472 *p_element_file << "\t" << node_indices[i];
00473 }
00474
00475 *p_element_file << "\t" << elem_data.AttributeValue;
00476
00477
00478 *p_element_file << "\n";
00479 }
00480 else
00481 {
00482 assert(SPACE_DIM == 3);
00483
00484
00485 VertexElementData elem_data_with_faces = this->GetNextElementWithFaces();
00486
00487
00488 std::vector<unsigned> node_indices = elem_data_with_faces.NodeIndices;
00489
00490
00491 *p_element_file << item_num << "\t" << node_indices.size();
00492
00493
00494 for (unsigned i=0; i<node_indices.size(); i++)
00495 {
00496 *p_element_file << "\t" << node_indices[i];
00497 }
00498
00499
00500 std::vector<ElementData> faces = elem_data_with_faces.Faces;
00501
00502
00503 *p_element_file << "\t" << faces.size();
00504
00505 for (unsigned j=0; j<faces.size(); j++)
00506 {
00507
00508 std::vector<unsigned> face_node_indices = faces[j].NodeIndices;
00509
00510
00511 *p_element_file << "\t" << faces[j].AttributeValue << "\t" << face_node_indices.size();
00512
00513
00514 for (unsigned i=0; i<face_node_indices.size(); i++)
00515 {
00516 *p_element_file << "\t" << face_node_indices[i];
00517 }
00518
00520 }
00521
00522 *p_element_file << "\t" << elem_data_with_faces.AttributeValue;
00523
00524
00525 *p_element_file << "\n";
00526 }
00527 }
00528
00529 *p_element_file << comment << "\n";
00530 p_element_file->close();
00531 }
00532
00534
00536
00537 template class VertexMeshWriter<1,1>;
00538 template class VertexMeshWriter<1,2>;
00539 template class VertexMeshWriter<1,3>;
00540 template class VertexMeshWriter<2,2>;
00541 template class VertexMeshWriter<2,3>;
00542 template class VertexMeshWriter<3,3>;