36 #include <boost/scoped_array.hpp>
37 #include "VtkMeshWriter.hpp"
38 #include "DistributedTetrahedralMesh.hpp"
39 #include "MixedDimensionMesh.hpp"
40 #include "NodesOnlyMesh.hpp"
43 #include "vtkQuadraticTetra.h"
44 #include "vtkQuadraticTriangle.h"
50 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
52 const std::string& rBaseName,
53 const bool& rCleanDirectory)
55 mWriteParallelFiles(false)
63 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
66 mpVtkUnstructedMesh->Delete();
69 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
73 vtkPoints* p_pts = vtkPoints::New(VTK_DOUBLE);
74 p_pts->GetData()->SetName(
"Vertex positions");
75 for (
unsigned item_num=0; item_num<this->GetNumNodes(); item_num++)
77 std::vector<double> current_item = this->GetNextNode();
79 for (
unsigned dim=SPACE_DIM; dim<3; dim++)
81 current_item.push_back(0.0);
83 assert(current_item.size() == 3);
84 p_pts->InsertPoint(item_num, current_item[0], current_item[1], current_item[2]);
86 mpVtkUnstructedMesh->SetPoints(p_pts);
90 for (
unsigned item_num=0; item_num<this->GetNumElements(); item_num++)
92 std::vector<unsigned> current_element = this->GetNextElement().NodeIndices;
94 assert((current_element.size() == ELEMENT_DIM + 1) || (current_element.size() == (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2));
97 if (ELEMENT_DIM == 3 && current_element.size() == 4)
99 p_cell = vtkTetra::New();
101 else if(ELEMENT_DIM == 3 && current_element.size() == 10)
103 p_cell = vtkQuadraticTetra::New();
105 else if (ELEMENT_DIM == 2 && current_element.size() == 3)
107 p_cell = vtkTriangle::New();
109 else if (ELEMENT_DIM == 2 && current_element.size() == 6)
111 p_cell = vtkQuadraticTriangle::New();
113 else if (ELEMENT_DIM == 1)
115 p_cell = vtkLine::New();
119 vtkIdList* p_cell_id_list = p_cell->GetPointIds();
120 for (
unsigned j = 0; j < current_element.size(); ++j)
122 p_cell_id_list->SetId(j, current_element[j]);
126 if (SPACE_DIM == 2 && current_element.size() == 6)
128 p_cell_id_list->SetId(3, current_element[5]);
129 p_cell_id_list->SetId(4, current_element[3]);
130 p_cell_id_list->SetId(5, current_element[4]);
133 mpVtkUnstructedMesh->InsertNextCell(p_cell->GetCellType(), p_cell_id_list);
140 for (
unsigned item_num=0; item_num<this->GetNumBoundaryFaces(); item_num++)
142 this->GetNextBoundaryElement();
147 if (this->GetNumCableElements() > 0)
151 std::vector<double> radii(this->GetNumElements(), 0.0);
152 for (
unsigned item_num=0; item_num<this->GetNumCableElements(); item_num++)
154 ElementData cable_element_data = this->GetNextCableElement();
155 std::vector<unsigned> current_element = cable_element_data.
NodeIndices;
157 assert(current_element.size() == 2);
158 vtkCell* p_cell=vtkLine::New();
159 vtkIdList* p_cell_id_list = p_cell->GetPointIds();
160 for (
unsigned j = 0; j < 2; ++j)
162 p_cell_id_list->SetId(j, current_element[j]);
164 mpVtkUnstructedMesh->InsertNextCell(p_cell->GetCellType(), p_cell_id_list);
167 AddCellData(
"Cable radius", radii);
172 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
177 out_stream p_vtu_file = this->mpOutputFileHandler->OpenOutputFile(fileName, std::ios::out | std::ios::app);
179 *p_vtu_file <<
"\n" << comment <<
"\n";
183 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
189 assert(mpVtkUnstructedMesh->CheckAttributes() == 0);
190 vtkXMLUnstructuredGridWriter* p_writer = vtkXMLUnstructuredGridWriter::New();
191 #if VTK_MAJOR_VERSION >= 6
192 p_writer->SetInputData(mpVtkUnstructedMesh);
194 p_writer->SetInput(mpVtkUnstructedMesh);
199 p_writer->SetCompressor(NULL);
201 std::string vtk_file_name = this->mpOutputFileHandler->GetOutputDirectoryFullPath() + this->mBaseName+
".vtu";
202 p_writer->SetFileName(vtk_file_name.c_str());
208 AddProvenance(this->mBaseName +
".vtu");
211 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
214 vtkDoubleArray* p_scalars = vtkDoubleArray::New();
215 p_scalars->SetName(dataName.c_str());
216 for (
unsigned i=0; i<dataPayload.size(); i++)
218 p_scalars->InsertNextValue(dataPayload[i]);
221 vtkCellData* p_cell_data = mpVtkUnstructedMesh->GetCellData();
222 p_cell_data->AddArray(p_scalars);
226 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
229 unsigned num_cell_arrays = mpVtkUnstructedMesh->GetCellData()->GetNumberOfArrays();
230 for (
unsigned i = 0; i < num_cell_arrays; i++)
232 vtkDataArray* array = mpVtkUnstructedMesh->GetCellData()->GetArray(i);
235 unsigned num_cable_pads = this->GetNumCableElements();
236 if (mWriteParallelFiles)
238 assert((
unsigned)array->GetNumberOfTuples() == this->mpDistributedMesh->GetNumLocalElements());
239 num_cable_pads = this->mpMixedMesh->GetNumLocalCableElements();
243 assert((
unsigned)array->GetNumberOfTuples() == this->GetNumElements());
247 assert(array->GetNumberOfComponents() <= 3);
248 double null_data[3] = {0.0, 0.0, 0.0};
251 for (
unsigned new_index = 0; new_index < num_cable_pads; new_index++)
253 array->InsertNextTuple(null_data);
259 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
262 vtkDoubleArray* p_vectors = vtkDoubleArray::New();
263 p_vectors->SetName(dataName.c_str());
264 p_vectors->SetNumberOfComponents(3);
265 for (
unsigned i=0; i<dataPayload.size(); i++)
267 for (
unsigned j=0; j<SPACE_DIM; j++)
269 p_vectors->InsertNextValue(dataPayload[i][j]);
272 for (
unsigned j=SPACE_DIM; j<3; j++)
274 p_vectors->InsertNextValue(0.0);
278 vtkCellData* p_cell_data = mpVtkUnstructedMesh->GetCellData();
279 p_cell_data->AddArray(p_vectors);
283 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
286 assert(SPACE_DIM != 1);
288 vtkDoubleArray* p_vectors = vtkDoubleArray::New();
289 p_vectors->SetName(dataName.c_str());
290 p_vectors->SetNumberOfComponents(SPACE_DIM*SPACE_DIM);
291 for (
unsigned i=0; i<dataPayload.size(); i++)
295 p_vectors->InsertNextValue(dataPayload[i](0));
296 p_vectors->InsertNextValue(dataPayload[i](1));
297 p_vectors->InsertNextValue(dataPayload[i](1));
298 p_vectors->InsertNextValue(dataPayload[i](2));
300 else if (SPACE_DIM == 3)
302 p_vectors->InsertNextValue(dataPayload[i](0));
303 p_vectors->InsertNextValue(dataPayload[i](1));
304 p_vectors->InsertNextValue(dataPayload[i](2));
305 p_vectors->InsertNextValue(dataPayload[i](1));
306 p_vectors->InsertNextValue(dataPayload[i](3));
307 p_vectors->InsertNextValue(dataPayload[i](4));
308 p_vectors->InsertNextValue(dataPayload[i](2));
309 p_vectors->InsertNextValue(dataPayload[i](4));
310 p_vectors->InsertNextValue(dataPayload[i](5));
314 vtkCellData* p_cell_data = mpVtkUnstructedMesh->GetCellData();
315 p_cell_data->AddArray(p_vectors);
319 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
322 assert(SPACE_DIM != 1);
324 vtkDoubleArray* p_vectors = vtkDoubleArray::New();
325 p_vectors->SetName(dataName.c_str());
326 p_vectors->SetNumberOfComponents(SPACE_DIM*SPACE_DIM);
327 for (
unsigned i=0; i<dataPayload.size(); i++)
331 p_vectors->InsertNextValue(dataPayload[i](0,0));
332 p_vectors->InsertNextValue(dataPayload[i](0,1));
333 p_vectors->InsertNextValue(dataPayload[i](1,0));
334 p_vectors->InsertNextValue(dataPayload[i](1,1));
336 else if (SPACE_DIM == 3)
338 p_vectors->InsertNextValue(dataPayload[i](0,0));
339 p_vectors->InsertNextValue(dataPayload[i](0,1));
340 p_vectors->InsertNextValue(dataPayload[i](0,2));
341 p_vectors->InsertNextValue(dataPayload[i](1,0));
342 p_vectors->InsertNextValue(dataPayload[i](1,1));
343 p_vectors->InsertNextValue(dataPayload[i](1,2));
344 p_vectors->InsertNextValue(dataPayload[i](2,0));
345 p_vectors->InsertNextValue(dataPayload[i](2,1));
346 p_vectors->InsertNextValue(dataPayload[i](2,2));
350 vtkCellData* p_cell_data = mpVtkUnstructedMesh->GetCellData();
351 p_cell_data->AddArray(p_vectors);
356 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
359 vtkDoubleArray* p_scalars = vtkDoubleArray::New();
360 p_scalars->SetName(dataName.c_str());
362 if (mWriteParallelFiles && this->mpDistributedMesh != NULL)
369 assert( dataPayload.size() == this->mpDistributedMesh->GetNumLocalNodes() );
370 dataPayload.resize( this->mpDistributedMesh->GetNumLocalNodes() + this->mpDistributedMesh->GetNumHaloNodes() );
379 unsigned number_of_nodes_to_send = mNodesToSendPerProcess[send_to].size();
380 unsigned number_of_nodes_to_receive = mNodesToReceivePerProcess[receive_from].size();
382 boost::scoped_array<double> send_data(
new double[number_of_nodes_to_send]);
383 boost::scoped_array<double> receive_data(
new double[number_of_nodes_to_receive]);
385 for (
unsigned node = 0; node < number_of_nodes_to_send; node++)
387 unsigned global_node_index = mNodesToSendPerProcess[send_to][node];
388 unsigned local_node_index = global_node_index
389 - this->mpDistributedMesh->GetDistributedVectorFactory()->GetLow();
390 send_data[node] = dataPayload[local_node_index];
396 ret = MPI_Sendrecv(send_data.get(), number_of_nodes_to_send,
399 receive_data.get(), number_of_nodes_to_receive,
402 PETSC_COMM_WORLD, &status);
404 assert ( ret == MPI_SUCCESS );
408 for (
unsigned node = 0; node < number_of_nodes_to_receive; node++ )
410 unsigned global_node_index = mNodesToReceivePerProcess[receive_from][node];
411 unsigned halo_index = mGlobalToNodeIndexMap[global_node_index];
412 assert( halo_index >= this->mpDistributedMesh->GetNumLocalNodes() );
413 dataPayload[halo_index] = receive_data[node];
419 for (
unsigned i=0; i<dataPayload.size(); i++)
421 p_scalars->InsertNextValue(dataPayload[i]);
424 vtkPointData* p_point_data = mpVtkUnstructedMesh->GetPointData();
425 p_point_data->AddArray(p_scalars);
430 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
433 vtkDoubleArray* p_vectors = vtkDoubleArray::New();
434 p_vectors->SetName(dataName.c_str());
436 if (mWriteParallelFiles)
443 assert( dataPayload.size() == this->mpDistributedMesh->GetNumLocalNodes() );
444 dataPayload.resize( this->mpDistributedMesh->GetNumLocalNodes() + this->mpDistributedMesh->GetNumHaloNodes() );
452 unsigned number_of_nodes_to_send = mNodesToSendPerProcess[send_to].size();
453 unsigned number_of_nodes_to_receive = mNodesToReceivePerProcess[receive_from].size();
455 boost::scoped_array<double> send_data(
new double[number_of_nodes_to_send * SPACE_DIM]);
456 boost::scoped_array<double> receive_data(
new double[number_of_nodes_to_receive * SPACE_DIM]);
458 for (
unsigned node = 0; node < number_of_nodes_to_send; node++)
460 unsigned global_node_index = mNodesToSendPerProcess[send_to][node];
461 unsigned local_node_index = global_node_index
462 - this->mpDistributedMesh->GetDistributedVectorFactory()->GetLow();
463 for (
unsigned j=0; j<SPACE_DIM; j++)
465 send_data[ node*SPACE_DIM + j ] = dataPayload[local_node_index][j];
471 ret = MPI_Sendrecv(send_data.get(), number_of_nodes_to_send * SPACE_DIM,
474 receive_data.get(), number_of_nodes_to_receive * SPACE_DIM,
477 PETSC_COMM_WORLD, &status);
479 assert ( ret == MPI_SUCCESS );
482 for (
unsigned node = 0; node < number_of_nodes_to_receive; node++ )
484 unsigned global_node_index = mNodesToReceivePerProcess[receive_from][node];
485 unsigned halo_index = mGlobalToNodeIndexMap[global_node_index];
486 assert( halo_index >= this->mpDistributedMesh->GetNumLocalNodes() );
487 for (
unsigned j=0; j<SPACE_DIM; j++)
489 dataPayload[halo_index][j] = receive_data[ node*SPACE_DIM + j ];
495 p_vectors->SetNumberOfComponents(3);
496 for (
unsigned i=0; i<dataPayload.size(); i++)
498 for (
unsigned j=0; j<SPACE_DIM; j++)
500 p_vectors->InsertNextValue(dataPayload[i][j]);
503 for (
unsigned j=SPACE_DIM; j<3; j++)
505 p_vectors->InsertNextValue(0.0);
509 vtkPointData* p_point_data = mpVtkUnstructedMesh->GetPointData();
510 p_point_data->AddArray(p_vectors);
514 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
517 assert(SPACE_DIM != 1);
519 vtkDoubleArray* p_vectors = vtkDoubleArray::New();
520 p_vectors->SetName(dataName.c_str());
521 p_vectors->SetNumberOfComponents(SPACE_DIM*SPACE_DIM);
522 for (
unsigned i=0; i<dataPayload.size(); i++)
526 p_vectors->InsertNextValue(dataPayload[i](0,0));
527 p_vectors->InsertNextValue(dataPayload[i](0,1));
528 p_vectors->InsertNextValue(dataPayload[i](1,0));
529 p_vectors->InsertNextValue(dataPayload[i](1,1));
531 else if (SPACE_DIM == 3)
533 p_vectors->InsertNextValue(dataPayload[i](0,0));
534 p_vectors->InsertNextValue(dataPayload[i](0,1));
535 p_vectors->InsertNextValue(dataPayload[i](0,2));
536 p_vectors->InsertNextValue(dataPayload[i](1,0));
537 p_vectors->InsertNextValue(dataPayload[i](1,1));
538 p_vectors->InsertNextValue(dataPayload[i](1,2));
539 p_vectors->InsertNextValue(dataPayload[i](2,0));
540 p_vectors->InsertNextValue(dataPayload[i](2,1));
541 p_vectors->InsertNextValue(dataPayload[i](2,2));
545 vtkPointData* p_point_data = mpVtkUnstructedMesh->GetPointData();
546 p_point_data->AddArray(p_vectors);
550 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
557 if (this->mpDistributedMesh == NULL && mpNodesOnlyMesh == NULL)
559 EXCEPTION(
"Cannot write parallel files using a sequential mesh");
567 mWriteParallelFiles =
true;
579 mGlobalToNodeIndexMap[node_iter->GetIndex()] = index;
584 if (this->mpDistributedMesh)
587 halo_iter != this->mpDistributedMesh->GetHaloNodeIteratorEnd();
590 mGlobalToNodeIndexMap[(*halo_iter)->GetIndex()] = index;
595 this->mpDistributedMesh->CalculateNodeExchange( mNodesToSendPerProcess, mNodesToReceivePerProcess );
600 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
603 bool keepOriginalElementIndexing)
609 if (
PetscTools::IsSequential() || !mWriteParallelFiles || (this->mpDistributedMesh == NULL && mpNodesOnlyMesh == NULL) )
616 vtkPoints* p_pts = vtkPoints::New(VTK_DOUBLE);
617 p_pts->GetData()->SetName(
"Vertex positions");
624 c_vector<double, SPACE_DIM> current_item = node_iter->rGetLocation();
627 p_pts->InsertNextPoint(current_item[0], current_item[1], current_item[2]);
629 else if (SPACE_DIM == 2)
631 p_pts->InsertNextPoint(current_item[0], current_item[1], 0.0);
635 p_pts->InsertNextPoint(current_item[0], 0.0, 0.0);
640 if (this->mpDistributedMesh)
643 halo_iter != this->mpDistributedMesh->GetHaloNodeIteratorEnd();
646 c_vector<double, SPACE_DIM> current_item = (*halo_iter)->rGetLocation();
649 p_pts->InsertNextPoint(current_item[0], current_item[1], current_item[2]);
651 else if (SPACE_DIM == 2)
653 p_pts->InsertNextPoint(current_item[0], current_item[1], 0.0);
657 p_pts->InsertNextPoint(current_item[0], 0.0, 0.0);
662 mpVtkUnstructedMesh->SetPoints(p_pts);
670 vtkCell* p_cell=NULL;
672 if (ELEMENT_DIM == 3)
674 p_cell = vtkTetra::New();
676 else if (ELEMENT_DIM == 2)
678 p_cell = vtkTriangle::New();
682 p_cell = vtkLine::New();
684 vtkIdList* p_cell_id_list = p_cell->GetPointIds();
685 for (
unsigned j = 0; j < ELEMENT_DIM+1; ++j)
687 unsigned global_node_index = elem_iter->GetNodeGlobalIndex(j);
688 p_cell_id_list->SetId(j, mGlobalToNodeIndexMap[global_node_index]);
690 mpVtkUnstructedMesh->InsertNextCell(p_cell->GetCellType(), p_cell_id_list);
694 if (this->mpMixedMesh )
700 elem_iter != this->mpMixedMesh->GetCableElementIteratorEnd();
703 radii.push_back((*elem_iter)->GetAttribute());
704 vtkCell* p_cell=vtkLine::New();
705 vtkIdList* p_cell_id_list = p_cell->GetPointIds();
706 for (
unsigned j = 0; j < 2; ++j)
708 unsigned global_node_index = (*elem_iter)->GetNodeGlobalIndex(j);
709 p_cell_id_list->SetId(j, mGlobalToNodeIndexMap[global_node_index]);
711 mpVtkUnstructedMesh->InsertNextCell(p_cell->GetCellType(), p_cell_id_list);
714 AddCellData(
"Cable radius", radii);
721 assert(mpVtkUnstructedMesh->CheckAttributes() == 0);
722 vtkXMLPUnstructuredGridWriter* p_writer = vtkXMLPUnstructuredGridWriter::New();
724 p_writer->SetDataModeToBinary();
732 #if VTK_MAJOR_VERSION >= 6
733 p_writer->SetInputData(mpVtkUnstructedMesh);
735 p_writer->SetInput(mpVtkUnstructedMesh);
740 p_writer->SetCompressor(NULL);
742 std::string pvtk_file_name = this->mpOutputFileHandler->GetOutputDirectoryFullPath() + this->mBaseName+
".pvtu";
743 p_writer->SetFileName(pvtk_file_name.c_str());
750 std::stringstream filepath;
752 AddProvenance(filepath.str());
756 AddProvenance(this->mBaseName+
".pvtu");
ElementIterator GetElementIteratorBegin(bool skipDeletedElements=true)
ElementIterator GetElementIteratorEnd()
#define EXCEPTION(message)
vtkUnstructuredGrid * mpVtkUnstructedMesh
std::vector< Node< SPACE_DIM > * >::const_iterator HaloNodeIterator
void SetParallelFiles(AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > &rMesh)
void AddCellData(std::string name, std::vector< double > data)
void AddProvenance(std::string fileName)
NodeIterator GetNodeIteratorEnd()
std::vector< unsigned > NodeIndices
void WriteFilesUsingMesh(AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > &rMesh, bool keepOriginalElementIndexing=true)
unsigned GetNumLocalElements() const
void AddTensorCellData(std::string name, std::vector< c_vector< double, SPACE_DIM *(SPACE_DIM+1)/2 > > data)
void AddTensorPointData(std::string name, std::vector< c_matrix< double, SPACE_DIM, SPACE_DIM > > data)
NodeIterator GetNodeIteratorBegin(bool skipDeletedNodes=true)
static std::string GetProvenanceString()
virtual void WriteFilesUsingMesh(AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > &rMesh, bool keepOriginalElementIndexing=true)
VtkMeshWriter(const std::string &rDirectory, const std::string &rBaseName, const bool &rCleanDirectory=true)
void AddPointData(std::string name, std::vector< double > data)
std::vector< Element< 1, SPACE_DIM > * >::const_iterator CableElementIterator