#include #include "FEAdaptor.h" #include "FEDataStructures.h" #include "vtkCPPVSMPipeline.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace { vtkCPProcessor* Processor = NULL; vtkUnstructuredGrid* VTKGrid; void BuildVTKGrid(Grid& grid) { // create the points information vtkNew pointArray; pointArray->SetNumberOfComponents(3); pointArray->SetArray(grid.GetPointsArray(), static_cast(grid.GetNumberOfPoints()*3), 1); vtkNew points; points->SetData(pointArray.GetPointer()); VTKGrid->SetPoints(points.GetPointer()); // create the cells size_t numCells = grid.GetNumberOfCells(); VTKGrid->Allocate(static_cast(numCells*9)); for(size_t cell=0;cellInsertNextCell(VTK_HEXAHEDRON, 8, tmp); } } void UpdateVTKAttributes(Grid& grid, Attributes& attributes) { if(VTKGrid->GetPointData()->GetNumberOfArrays() == 0) { // velocity array vtkNew velocity; velocity->SetName("velocity"); velocity->SetNumberOfComponents(3); velocity->SetNumberOfTuples(static_cast(grid.GetNumberOfPoints())); VTKGrid->GetPointData()->AddArray(velocity.GetPointer()); } if(VTKGrid->GetCellData()->GetNumberOfArrays() == 0) { // pressure array vtkNew pressure; pressure->SetName("pressure"); pressure->SetNumberOfComponents(1); VTKGrid->GetCellData()->AddArray(pressure.GetPointer()); } vtkDoubleArray* velocity = vtkDoubleArray::SafeDownCast( VTKGrid->GetPointData()->GetArray("velocity")); // The velocity array is ordered as vx0,vx1,vx2,..,vy0,vy1,vy2,..,vz0,vz1,vz2,.. // so we need to create a full copy of it with VTK's ordering of // vx0,vy0,vz0,vx1,vy1,vz1,.. double* velocityData = attributes.GetVelocityArray(); vtkIdType numTuples = velocity->GetNumberOfTuples(); for(vtkIdType i=0;iSetTupleValue(i, values); } vtkFloatArray* pressure = vtkFloatArray::SafeDownCast( VTKGrid->GetCellData()->GetArray("pressure")); // The pressure array is a scalar array so we can reuse // memory as long as we ordered the points properly. float* pressureData = attributes.GetPressureArray(); pressure->SetArray(pressureData, static_cast(grid.GetNumberOfCells()), 1); } void BuildVTKDataStructures(Grid& grid, Attributes& attributes) { if(VTKGrid == NULL) { // The grid structure isn't changing so we only build it // the first time it's needed. If we needed the memory // we could delete it and rebuild as necessary. VTKGrid = vtkUnstructuredGrid::New(); BuildVTKGrid(grid); } UpdateVTKAttributes(grid, attributes); } } namespace FEAdaptor { void Initialize(int outputFrequency, std::string fileName) { if(Processor == NULL) { Processor = vtkCPProcessor::New(); Processor->Initialize(); } vtkSMSession::ConnectToSelf(); vtkNew pipeline; pipeline->Initialize(outputFrequency, fileName); Processor->AddPipeline(pipeline.GetPointer()); } void Finalize() { if(Processor) { Processor->Delete(); Processor = NULL; } if(VTKGrid) { VTKGrid->Delete(); VTKGrid = NULL; } } void CoProcess(Grid& grid, Attributes& attributes, double time, unsigned int timeStep, bool lastTimeStep) { vtkNew dataDescription; dataDescription->AddInput("input"); dataDescription->SetTimeData(time, timeStep); if(lastTimeStep == true) { // assume that we want to all the pipelines to execute if it // is the last time step. dataDescription->ForceOutputOn(); } if(Processor->RequestDataDescription(dataDescription.GetPointer()) != 0) { BuildVTKDataStructures(grid, attributes); dataDescription->GetInputDescriptionByName("input")->SetGrid(VTKGrid); Processor->CoProcess(dataDescription.GetPointer()); } } } // end of Catalyst namespace