├── CFullExample ├── CMakeLists.txt ├── FEAdaptor.cxx ├── FEAdaptor.h ├── FEDataStructures.c ├── FEDataStructures.h ├── FEDriver.c └── SampleScripts │ └── feslicescript.py ├── CFullExample2 ├── CMakeLists.txt ├── FEAdaptor.cxx ├── FEAdaptor.h ├── FEDataStructures.c ├── FEDataStructures.h ├── FEDriver.c └── SampleScripts │ └── feslicescript.py ├── CMakeLists.txt ├── CxxFullExample ├── CMakeLists.txt ├── FEAdaptor.cxx ├── FEAdaptor.h ├── FEDataStructures.cxx ├── FEDataStructures.h ├── FEDriver.cxx └── SampleScripts │ ├── feslicecinema.py │ └── feslicescript.py ├── CxxImageDataExample ├── CMakeLists.txt ├── FEAdaptor.cxx ├── FEAdaptor.h ├── FEDataStructures.cxx ├── FEDataStructures.h ├── FEDriver.cxx └── SampleScripts │ └── feslicescript.py ├── CxxMappedDataArrayExample ├── CMakeLists.txt ├── FEAdaptor.cxx ├── FEAdaptor.h ├── FEDataStructures.cxx ├── FEDataStructures.h ├── FEDriver.cxx ├── SampleScripts │ └── feslicescript.py ├── vtkCPMappedVectorArrayTemplate.h └── vtkCPMappedVectorArrayTemplate.txx ├── CxxMultiPieceExample ├── CMakeLists.txt ├── FEAdaptor.cxx ├── FEAdaptor.h ├── FEDataStructures.cxx ├── FEDataStructures.h ├── FEDriver.cxx └── SampleScripts │ └── feslicescript.py ├── CxxNonOverlappingAMRExample ├── CMakeLists.txt ├── FEAdaptor.cxx ├── FEAdaptor.h ├── FEDriver.cxx └── SampleScripts │ └── feslicescript.py ├── CxxOverlappingAMRExample ├── CMakeLists.txt ├── FEAdaptor.cxx ├── FEAdaptor.h ├── FEDriver.cxx └── SampleScripts │ └── feslicescript.py ├── CxxPVSMPipelineExample ├── CMakeLists.txt ├── FEAdaptor.cxx ├── FEAdaptor.h ├── FEDataStructures.cxx ├── FEDataStructures.h ├── FEDriver.cxx ├── vtkCPPVSMPipeline.cxx └── vtkCPPVSMPipeline.h ├── CxxVTKPipelineExample ├── CMakeLists.txt ├── FEAdaptor.cxx ├── FEAdaptor.h ├── FEDataStructures.cxx ├── FEDataStructures.h ├── FEDriver.cxx ├── vtkCPVTKPipeline.cxx └── vtkCPVTKPipeline.h ├── Fortran90FullExample ├── CMakeLists.txt ├── FECxxAdaptor.cxx ├── FEDriver.f90 ├── FEFortranAdaptor.f90 └── SampleScripts │ └── coproc.py ├── FortranPoissonSolver ├── Box.F90 ├── CMakeLists.txt ├── ConjugateGradient.F90 ├── FECxxAdaptor.cxx ├── FEDriver.F90 ├── FEFortranAdaptor.F90 ├── PoissonDiscretization.F90 ├── SampleScripts │ └── coproc.py └── SparseMatrix.F90 ├── LICENSE.md ├── MPISubCommunicatorExample ├── CMakeLists.txt ├── FEAdaptor.cxx ├── FEAdaptor.h ├── FEDataStructures.cxx ├── FEDataStructures.h ├── FEDriver.cxx └── SampleScripts │ └── feslicescript.py ├── PythonDolfinExample ├── CMakeLists.txt ├── CatalystScriptTest.py ├── Data │ └── lshape.xml.gz ├── README.txt ├── run-catalyst-step1.sh.in ├── run-catalyst-step2.sh.in ├── run-catalyst-step3.sh.in ├── run-catalyst-step4.sh.in ├── run-catalyst-step6.sh.in ├── run-original.sh.in ├── simulation-catalyst-step1.py ├── simulation-catalyst-step2.py ├── simulation-catalyst-step3.py ├── simulation-catalyst-step4.py ├── simulation-catalyst-step6.py ├── simulation-env.py.in └── simulation.py ├── PythonFullExample ├── coprocessor.py ├── cpscript.py ├── fedatastructures.py └── fedriver.py ├── README └── SampleScripts ├── allinputsgridwriter.py └── gridwriter.py /CFullExample/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.8) 2 | project(CatalystCFullExample C) 3 | 4 | set(USE_CATALYST ON CACHE BOOL "Link the simulator with Catalyst") 5 | if(USE_CATALYST) 6 | # we only need C++ compilers if we're building the Adaptor 7 | enable_language(CXX) 8 | find_package(ParaView 4.1 REQUIRED COMPONENTS vtkPVPythonCatalyst) 9 | include("${PARAVIEW_USE_FILE}") 10 | set(Adaptor_SRCS 11 | FEAdaptor.cxx 12 | ) 13 | add_library(CFullExampleAdaptor ${Adaptor_SRCS}) 14 | target_link_libraries(CFullExampleAdaptor vtkPVPythonCatalyst) 15 | add_definitions("-DUSE_CATALYST") 16 | if(NOT PARAVIEW_USE_MPI) 17 | message(SEND_ERROR "ParaView must be built with MPI enabled") 18 | endif() 19 | else() 20 | find_package(MPI REQUIRED) 21 | include_directories(${MPI_C_INCLUDE_PATH}) 22 | endif() 23 | 24 | add_executable(CFullExample FEDriver.c FEDataStructures.c) 25 | if(USE_CATALYST) 26 | target_link_libraries(CFullExample LINK_PRIVATE CFullExampleAdaptor) 27 | include(vtkModuleMacros) 28 | include(vtkMPI) 29 | vtk_mpi_link(CFullExample) 30 | else() 31 | target_link_libraries(CFullExample LINK_PRIVATE ${MPI_LIBRARIES}) 32 | endif() 33 | 34 | option(BUILD_TESTING "Build Testing" OFF) 35 | # Setup testing. 36 | if (BUILD_TESTING) 37 | include(CTest) 38 | add_test(CFullExampleTest CFullExample ${CMAKE_CURRENT_SOURCE_DIR}/SampleScripts/feslicescript.py) 39 | endif() 40 | -------------------------------------------------------------------------------- /CFullExample/FEAdaptor.h: -------------------------------------------------------------------------------- 1 | #ifndef FEADAPTOR_HEADER 2 | #define FEADAPTOR_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" 6 | { 7 | #endif 8 | void CatalystInitialize(int numScripts, char* scripts[]); 9 | 10 | void CatalystFinalize(); 11 | 12 | void CatalystCoProcess(unsigned int numberOfPoints, double* pointsData, 13 | unsigned int numberOfCells, unsigned int* cellsDAta, 14 | double* velocityData, float* pressureData, double time, 15 | unsigned int timeStep, int lastTimeStep); 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | #endif 20 | -------------------------------------------------------------------------------- /CFullExample/FEDataStructures.c: -------------------------------------------------------------------------------- 1 | #include "FEDataStructures.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | void InitializeGrid(Grid* grid, const unsigned int numPoints[3], const double spacing[3] ) 8 | { 9 | grid->NumberOfPoints = 0; 10 | grid->Points = 0; 11 | grid->NumberOfCells = 0; 12 | grid->Cells = 0; 13 | if(numPoints[0] == 0 || numPoints[1] == 0 || numPoints[2] == 0) 14 | { 15 | printf("Must have a non-zero amount of points in each direction.\n"); 16 | } 17 | // in parallel, we do a simple partitioning in the x-direction. 18 | int mpiSize = 1; 19 | int mpiRank = 0; 20 | MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); 21 | MPI_Comm_size(MPI_COMM_WORLD, &mpiSize); 22 | 23 | unsigned int startXPoint = mpiRank*numPoints[0]/mpiSize; 24 | unsigned int endXPoint = (mpiRank+1)*numPoints[0]/mpiSize; 25 | if(mpiSize != mpiRank+1) 26 | { 27 | endXPoint++; 28 | } 29 | 30 | // create the points -- slowest in the x and fastest in the z directions 31 | if(grid->Points != 0) 32 | { 33 | free(grid->Points); 34 | } 35 | unsigned int numXPoints = endXPoint - startXPoint; 36 | grid->Points = (double*) malloc(3*sizeof(double)*numPoints[1]*numPoints[2]*numXPoints); 37 | unsigned int counter = 0; 38 | unsigned int i, j, k; 39 | for(i=startXPoint;iPoints[counter] = i*spacing[0]; 46 | grid->Points[counter+1] = j*spacing[1]; 47 | grid->Points[counter+2] = k*spacing[2]; 48 | counter += 3; 49 | } 50 | } 51 | } 52 | grid->NumberOfPoints = numPoints[1]*numPoints[2]*numXPoints; 53 | // create the hex cells 54 | unsigned int cellPoints[8]; 55 | if(grid->Cells != 0) 56 | { 57 | free(grid->Cells); 58 | } 59 | grid->Cells = (unsigned int*) malloc(8*sizeof(unsigned int)*(numPoints[1]-1)*(numPoints[2]-1)*(numXPoints-1)); 60 | counter = 0; 61 | for(i=0;iCells[counter] = i*numPoints[1]*numPoints[2] + 68 | j*numPoints[2] + k; 69 | grid->Cells[counter+1] = (i+1)*numPoints[1]*numPoints[2] + 70 | j*numPoints[2] + k; 71 | grid->Cells[counter+2] = (i+1)*numPoints[1]*numPoints[2] + 72 | (j+1)*numPoints[2] + k; 73 | grid->Cells[counter+3] = i*numPoints[1]*numPoints[2] + 74 | (j+1)*numPoints[2] + k; 75 | grid->Cells[counter+4] = i*numPoints[1]*numPoints[2] + 76 | j*numPoints[2] + k+1; 77 | grid->Cells[counter+5] = (i+1)*numPoints[1]*numPoints[2] + 78 | j*numPoints[2] + k+1; 79 | grid->Cells[counter+6] = (i+1)*numPoints[1]*numPoints[2] + 80 | (j+1)*numPoints[2] + k+1; 81 | grid->Cells[counter+7] = i*numPoints[1]*numPoints[2] + 82 | (j+1)*numPoints[2] + k+1; 83 | counter += 8; 84 | } 85 | } 86 | } 87 | grid->NumberOfCells = (numPoints[1]-1)*(numPoints[2]-1)*(numXPoints-1); 88 | } 89 | 90 | void FinalizeGrid(Grid* grid) 91 | { 92 | if(grid->Points) 93 | { 94 | free(grid->Points); 95 | grid->Points = 0; 96 | } 97 | if(grid->Cells) 98 | { 99 | free(grid->Cells); 100 | grid->Cells = 0; 101 | } 102 | grid->NumberOfPoints = 0; 103 | grid->NumberOfCells = 0; 104 | } 105 | 106 | void InitializeAttributes(Attributes* attributes, Grid* grid) 107 | { 108 | attributes->GridPtr = grid; 109 | attributes->Velocity = 0; 110 | attributes->Pressure = 0; 111 | } 112 | 113 | void UpdateFields(Attributes* attributes, double time) 114 | { 115 | unsigned int numPoints = attributes->GridPtr->NumberOfPoints; 116 | if(attributes->Velocity != 0) 117 | { 118 | free(attributes->Velocity); 119 | } 120 | attributes->Velocity = (double*) malloc(sizeof(double)*numPoints*3); 121 | unsigned int i; 122 | for(i=0;iVelocity[i] = 0; 125 | attributes->Velocity[i+numPoints] = attributes->GridPtr->Points[i*3+1]*time; 126 | attributes->Velocity[i+2*numPoints] = 0; 127 | } 128 | unsigned int numCells = attributes->GridPtr->NumberOfCells; 129 | if(attributes->Pressure != 0) 130 | { 131 | free(attributes->Pressure); 132 | } 133 | attributes->Pressure = (float*) malloc(sizeof(float)*numCells); 134 | for(i=0;iPressure[i] = 0; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /CFullExample/FEDataStructures.h: -------------------------------------------------------------------------------- 1 | #ifndef FEDATASTRUCTURES_HEADER 2 | #define FEDATASTRUCTURES_HEADER 3 | 4 | typedef struct Grid 5 | { 6 | unsigned int NumberOfPoints; 7 | double* Points; 8 | unsigned int NumberOfCells; 9 | unsigned int* Cells; 10 | } Grid; 11 | 12 | void InitializeGrid(Grid* grid, const unsigned int numPoints[3], const double spacing[3]); 13 | void FinalizeGrid(Grid*); 14 | 15 | typedef struct Attributes 16 | { 17 | // A structure for generating and storing point and cell fields. 18 | // Velocity is stored at the points and pressure is stored 19 | // for the cells. The current velocity profile is for a 20 | // shearing flow with U(y,t) = y*t, V = 0 and W = 0. 21 | // Pressure is constant through the domain. 22 | double* Velocity; 23 | float* Pressure; 24 | Grid* GridPtr; 25 | } Attributes; 26 | 27 | void InitializeAttributes(Attributes* attributes, Grid* grid); 28 | void FinalizeAttributes(Attributes* attributes); 29 | void UpdateFields(Attributes* attributes, double time); 30 | #endif 31 | -------------------------------------------------------------------------------- /CFullExample/FEDriver.c: -------------------------------------------------------------------------------- 1 | #include "FEDataStructures.h" 2 | #include 3 | 4 | #ifdef USE_CATALYST 5 | #include "FEAdaptor.h" 6 | #endif 7 | 8 | // Example of a C adaptor for a simulation code 9 | // where the simulation code has a fixed topology 10 | // grid. We treat the grid as an unstructured 11 | // grid even though in the example provided it 12 | // would be best described as a vtkImageData. 13 | // Also, the points are stored in an inconsistent 14 | // manner with respect to the velocity vector. 15 | // This is purposefully done to demonstrate 16 | // the different approaches for getting data 17 | // into Catalyst. In this example we don't 18 | // use any of the Fortran/C API provided in 19 | // Catalyst. That is in CFullExample2. 20 | // Note that through configuration 21 | // that the driver can be run without linking 22 | // to Catalyst. 23 | 24 | int main(int argc, char* argv[]) 25 | { 26 | MPI_Init(&argc, &argv); 27 | Grid grid = (Grid) { .NumberOfPoints = 0, .Points = 0, .NumberOfCells = 0, .Cells = 0}; 28 | unsigned int numPoints[3] = {70, 60, 44}; 29 | double spacing[3] = {1, 1.1, 1.3}; 30 | InitializeGrid(&grid, numPoints, spacing); 31 | Attributes attributes; 32 | InitializeAttributes(&attributes, &grid); 33 | 34 | #ifdef USE_CATALYST 35 | CatalystInitialize(argc, argv); 36 | #endif 37 | unsigned int numberOfTimeSteps = 100; 38 | unsigned int timeStep; 39 | for(timeStep=0;timeStep 2 | #include "FEAdaptor.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | namespace 20 | { 21 | vtkSmartPointer VTKGrid; 22 | 23 | void BuildVTKGrid(unsigned int numberOfPoints, double* pointsData, 24 | unsigned int numberOfCells, unsigned int* cellsData) 25 | { 26 | // create the points information 27 | vtkNew pointArray; 28 | pointArray->SetNumberOfComponents(3); 29 | pointArray->SetArray(pointsData, static_cast(numberOfPoints*3), 1); 30 | vtkNew points; 31 | points->SetData(pointArray.GetPointer()); 32 | VTKGrid->SetPoints(points.GetPointer()); 33 | 34 | // create the cells 35 | VTKGrid->Allocate(static_cast(numberOfCells*9)); 36 | for(unsigned int cell=0;cellInsertNextCell(VTK_HEXAHEDRON, 8, tmp); 42 | } 43 | } 44 | 45 | void UpdateVTKAttributes(unsigned int numberOfPoints, double* velocityData, 46 | unsigned int numberOfCells, float* pressureData) 47 | { 48 | if(VTKGrid->GetPointData()->GetNumberOfArrays() == 0) 49 | { 50 | // velocity array 51 | vtkNew velocity; 52 | velocity->SetName("velocity"); 53 | velocity->SetNumberOfComponents(3); 54 | velocity->SetNumberOfTuples(static_cast(numberOfPoints)); 55 | VTKGrid->GetPointData()->AddArray(velocity.GetPointer()); 56 | } 57 | if(VTKGrid->GetCellData()->GetNumberOfArrays() == 0) 58 | { 59 | // pressure array 60 | vtkNew pressure; 61 | pressure->SetName("pressure"); 62 | pressure->SetNumberOfComponents(1); 63 | VTKGrid->GetCellData()->AddArray(pressure.GetPointer()); 64 | } 65 | vtkDoubleArray* velocity = vtkDoubleArray::SafeDownCast( 66 | VTKGrid->GetPointData()->GetArray("velocity")); 67 | // The velocity array is ordered as vx0,vx1,vx2,..,vy0,vy1,vy2,..,vz0,vz1,vz2,.. 68 | // so we need to create a full copy of it with VTK's ordering of 69 | // vx0,vy0,vz0,vx1,vy1,vz1,.. 70 | for(unsigned int i=0;iSetTupleValue(i, values); 75 | } 76 | 77 | vtkFloatArray* pressure = vtkFloatArray::SafeDownCast( 78 | VTKGrid->GetCellData()->GetArray("pressure")); 79 | // The pressure array is a scalar array so we can reuse 80 | // memory as long as we ordered the points properly. 81 | pressure->SetArray(pressureData, static_cast(numberOfCells), 1); 82 | } 83 | 84 | void BuildVTKDataStructures(unsigned int numberOfPoints, double* points, double* velocity, 85 | unsigned int numberOfCells, unsigned int* cells, float* pressure) 86 | { 87 | if(VTKGrid == NULL) 88 | { 89 | // The grid structure isn't changing so we only build it 90 | // the first time it's needed. If we needed the memory 91 | // we could delete it and rebuild as necessary. 92 | VTKGrid = vtkSmartPointer::New(); 93 | BuildVTKGrid(numberOfPoints, points, numberOfCells, cells); 94 | } 95 | UpdateVTKAttributes(numberOfPoints, velocity, numberOfCells, pressure); 96 | } 97 | } 98 | 99 | void CatalystCoProcess(unsigned int numberOfPoints, double* pointsData, 100 | unsigned int numberOfCells, unsigned int* cellsData, 101 | double* velocityData, float* pressureData, double time, 102 | unsigned int timeStep, int lastTimeStep) 103 | { 104 | vtkCPProcessor* processor = vtkCPAdaptorAPI::GetCoProcessor(); 105 | vtkCPDataDescription* dataDescription = vtkCPAdaptorAPI::GetCoProcessorData(); 106 | if(processor == NULL || dataDescription == NULL) 107 | { 108 | cerr << "ERROR: Catalyst not properly initialized.\n"; 109 | return; 110 | } 111 | 112 | dataDescription->AddInput("input"); 113 | dataDescription->SetTimeData(time, timeStep); 114 | if(lastTimeStep == true) 115 | { 116 | // assume that we want to all the pipelines to execute if it 117 | // is the last time step. 118 | dataDescription->ForceOutputOn(); 119 | } 120 | if(processor->RequestDataDescription(dataDescription) != 0) 121 | { 122 | BuildVTKDataStructures(numberOfPoints, pointsData, velocityData, 123 | numberOfCells, cellsData, pressureData); 124 | dataDescription->GetInputDescriptionByName("input")->SetGrid(VTKGrid); 125 | processor->CoProcess(dataDescription); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /CFullExample2/FEAdaptor.h: -------------------------------------------------------------------------------- 1 | #ifndef FEADAPTOR_HEADER 2 | #define FEADAPTOR_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" 6 | { 7 | #endif 8 | void CatalystCoProcess(unsigned int numberOfPoints, double* pointsData, 9 | unsigned int numberOfCells, unsigned int* cellsDAta, 10 | double* velocityData, float* pressureData, double time, 11 | unsigned int timeStep, int lastTimeStep); 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | #endif 16 | -------------------------------------------------------------------------------- /CFullExample2/FEDataStructures.c: -------------------------------------------------------------------------------- 1 | #include "FEDataStructures.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | void InitializeGrid(Grid* grid, const unsigned int numPoints[3], const double spacing[3] ) 8 | { 9 | grid->NumberOfPoints = 0; 10 | grid->Points = 0; 11 | grid->NumberOfCells = 0; 12 | grid->Cells = 0; 13 | if(numPoints[0] == 0 || numPoints[1] == 0 || numPoints[2] == 0) 14 | { 15 | printf("Must have a non-zero amount of points in each direction.\n"); 16 | } 17 | // in parallel, we do a simple partitioning in the x-direction. 18 | int mpiSize = 1; 19 | int mpiRank = 0; 20 | MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); 21 | MPI_Comm_size(MPI_COMM_WORLD, &mpiSize); 22 | 23 | unsigned int startXPoint = mpiRank*numPoints[0]/mpiSize; 24 | unsigned int endXPoint = (mpiRank+1)*numPoints[0]/mpiSize; 25 | if(mpiSize != mpiRank+1) 26 | { 27 | endXPoint++; 28 | } 29 | 30 | // create the points -- slowest in the x and fastest in the z directions 31 | if(grid->Points != 0) 32 | { 33 | free(grid->Points); 34 | } 35 | unsigned int numXPoints = endXPoint - startXPoint; 36 | grid->Points = (double*) malloc(3*sizeof(double)*numPoints[1]*numPoints[2]*numXPoints); 37 | unsigned int counter = 0; 38 | unsigned int i, j, k; 39 | for(i=startXPoint;iPoints[counter] = i*spacing[0]; 46 | grid->Points[counter+1] = j*spacing[1]; 47 | grid->Points[counter+2] = k*spacing[2]; 48 | counter += 3; 49 | } 50 | } 51 | } 52 | grid->NumberOfPoints = numPoints[1]*numPoints[2]*numXPoints; 53 | // create the hex cells 54 | unsigned int cellPoints[8]; 55 | if(grid->Cells != 0) 56 | { 57 | free(grid->Cells); 58 | } 59 | grid->Cells = (unsigned int*) malloc(8*sizeof(unsigned int)*(numPoints[1]-1)*(numPoints[2]-1)*(numXPoints-1)); 60 | counter = 0; 61 | for(i=0;iCells[counter] = i*numPoints[1]*numPoints[2] + 68 | j*numPoints[2] + k; 69 | grid->Cells[counter+1] = (i+1)*numPoints[1]*numPoints[2] + 70 | j*numPoints[2] + k; 71 | grid->Cells[counter+2] = (i+1)*numPoints[1]*numPoints[2] + 72 | (j+1)*numPoints[2] + k; 73 | grid->Cells[counter+3] = i*numPoints[1]*numPoints[2] + 74 | (j+1)*numPoints[2] + k; 75 | grid->Cells[counter+4] = i*numPoints[1]*numPoints[2] + 76 | j*numPoints[2] + k+1; 77 | grid->Cells[counter+5] = (i+1)*numPoints[1]*numPoints[2] + 78 | j*numPoints[2] + k+1; 79 | grid->Cells[counter+6] = (i+1)*numPoints[1]*numPoints[2] + 80 | (j+1)*numPoints[2] + k+1; 81 | grid->Cells[counter+7] = i*numPoints[1]*numPoints[2] + 82 | (j+1)*numPoints[2] + k+1; 83 | counter += 8; 84 | } 85 | } 86 | } 87 | grid->NumberOfCells = (numPoints[1]-1)*(numPoints[2]-1)*(numXPoints-1); 88 | } 89 | 90 | void FinalizeGrid(Grid* grid) 91 | { 92 | if(grid->Points) 93 | { 94 | free(grid->Points); 95 | grid->Points = 0; 96 | } 97 | if(grid->Cells) 98 | { 99 | free(grid->Cells); 100 | grid->Cells = 0; 101 | } 102 | grid->NumberOfPoints = 0; 103 | grid->NumberOfCells = 0; 104 | } 105 | 106 | void InitializeAttributes(Attributes* attributes, Grid* grid) 107 | { 108 | attributes->GridPtr = grid; 109 | attributes->Velocity = 0; 110 | attributes->Pressure = 0; 111 | } 112 | 113 | void UpdateFields(Attributes* attributes, double time) 114 | { 115 | unsigned int numPoints = attributes->GridPtr->NumberOfPoints; 116 | if(attributes->Velocity != 0) 117 | { 118 | free(attributes->Velocity); 119 | } 120 | attributes->Velocity = (double*) malloc(sizeof(double)*numPoints*3); 121 | unsigned int i; 122 | for(i=0;iVelocity[i] = 0; 125 | attributes->Velocity[i+numPoints] = attributes->GridPtr->Points[i*3+1]*time; 126 | attributes->Velocity[i+2*numPoints] = 0; 127 | } 128 | unsigned int numCells = attributes->GridPtr->NumberOfCells; 129 | if(attributes->Pressure != 0) 130 | { 131 | free(attributes->Pressure); 132 | } 133 | attributes->Pressure = (float*) malloc(sizeof(float)*numCells); 134 | for(i=0;iPressure[i] = 0; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /CFullExample2/FEDataStructures.h: -------------------------------------------------------------------------------- 1 | #ifndef FEDATASTRUCTURES_HEADER 2 | #define FEDATASTRUCTURES_HEADER 3 | 4 | typedef struct Grid 5 | { 6 | unsigned int NumberOfPoints; 7 | double* Points; 8 | unsigned int NumberOfCells; 9 | unsigned int* Cells; 10 | } Grid; 11 | 12 | void InitializeGrid(Grid* grid, const unsigned int numPoints[3], const double spacing[3]); 13 | void FinalizeGrid(Grid*); 14 | 15 | typedef struct Attributes 16 | { 17 | // A structure for generating and storing point and cell fields. 18 | // Velocity is stored at the points and pressure is stored 19 | // for the cells. The current velocity profile is for a 20 | // shearing flow with U(y,t) = y*t, V = 0 and W = 0. 21 | // Pressure is constant through the domain. 22 | double* Velocity; 23 | float* Pressure; 24 | Grid* GridPtr; 25 | } Attributes; 26 | 27 | void InitializeAttributes(Attributes* attributes, Grid* grid); 28 | void FinalizeAttributes(Attributes* attributes); 29 | void UpdateFields(Attributes* attributes, double time); 30 | #endif 31 | -------------------------------------------------------------------------------- /CFullExample2/FEDriver.c: -------------------------------------------------------------------------------- 1 | #include "FEDataStructures.h" 2 | #include 3 | 4 | #ifdef USE_CATALYST 5 | #include "FEAdaptor.h" 6 | #include 7 | #include 8 | #include 9 | #endif 10 | 11 | // Example of a C adaptor for a simulation code 12 | // where the simulation code has a fixed topology 13 | // grid. We treat the grid as an unstructured 14 | // grid even though in the example provided it 15 | // would be best described as a vtkImageData. 16 | // Also, the points are stored in an inconsistent 17 | // manner with respect to the velocity vector. 18 | // This is purposefully done to demonstrate 19 | // the different approaches for getting data 20 | // into Catalyst. In this example we use 21 | // some of the API in CPythonAdaptorAPI.h 22 | // to assist in setting the problem up. 23 | // CFullExample does essentially the same 24 | // thing but without using the existing 25 | // helper API. Note that through configuration 26 | // that the driver can be run without linking 27 | // to Catalyst. 28 | 29 | int main(int argc, char* argv[]) 30 | { 31 | MPI_Init(&argc, &argv); 32 | Grid grid = (Grid) { .NumberOfPoints = 0, .Points = 0, .NumberOfCells = 0, .Cells = 0}; 33 | unsigned int numPoints[3] = {70, 60, 44}; 34 | double spacing[3] = {1, 1.1, 1.3}; 35 | InitializeGrid(&grid, numPoints, spacing); 36 | Attributes attributes; 37 | InitializeAttributes(&attributes, &grid); 38 | 39 | #ifdef USE_CATALYST 40 | int fileNameLength = 0; 41 | fileNameLength = strlen(argv[1]); 42 | coprocessorinitializewithpython(argv[1], &fileNameLength); 43 | int i; 44 | for(i=2;i 4 | #include 5 | 6 | Grid::Grid() 7 | {} 8 | 9 | void Grid::Initialize(const unsigned int numPoints[3], const double spacing[3] ) 10 | { 11 | if(numPoints[0] == 0 || numPoints[1] == 0 || numPoints[2] == 0) 12 | { 13 | std::cerr << "Must have a non-zero amount of points in each direction.\n"; 14 | } 15 | // in parallel, we do a simple partitioning in the x-direction. 16 | int mpiSize = 1; 17 | int mpiRank = 0; 18 | MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); 19 | MPI_Comm_size(MPI_COMM_WORLD, &mpiSize); 20 | 21 | unsigned int startXPoint = mpiRank*numPoints[0]/mpiSize; 22 | unsigned int endXPoint = (mpiRank+1)*numPoints[0]/mpiSize; 23 | if(mpiSize != mpiRank+1) 24 | { 25 | endXPoint++; 26 | } 27 | 28 | // create the points -- slowest in the x and fastest in the z directions 29 | double coord[3] = {0,0,0}; 30 | for(unsigned int i=startXPoint;iPoints)); 41 | } 42 | } 43 | } 44 | // create the hex cells 45 | unsigned int cellPoints[8]; 46 | unsigned int numXPoints = endXPoint - startXPoint; 47 | for(unsigned int i=0;iCells)); 70 | } 71 | } 72 | } 73 | } 74 | 75 | size_t Grid::GetNumberOfPoints() 76 | { 77 | return this->Points.size()/3; 78 | } 79 | 80 | size_t Grid::GetNumberOfCells() 81 | { 82 | return this->Cells.size()/8; 83 | } 84 | 85 | double* Grid::GetPointsArray() 86 | { 87 | if(this->Points.empty()) 88 | { 89 | return NULL; 90 | } 91 | return &(this->Points[0]); 92 | } 93 | 94 | double* Grid::GetPoint(size_t pointId) 95 | { 96 | if(pointId >= this->Points.size()) 97 | { 98 | return NULL; 99 | } 100 | return &(this->Points[pointId*3]); 101 | } 102 | 103 | unsigned int* Grid::GetCellPoints(size_t cellId) 104 | { 105 | if(cellId >= this->Cells.size()) 106 | { 107 | return NULL; 108 | } 109 | return &(this->Cells[cellId*8]); 110 | } 111 | 112 | Attributes::Attributes() 113 | { 114 | this->GridPtr = NULL; 115 | } 116 | 117 | void Attributes::Initialize(Grid* grid) 118 | { 119 | this->GridPtr = grid; 120 | } 121 | 122 | void Attributes::UpdateFields(double time) 123 | { 124 | size_t numPoints = this->GridPtr->GetNumberOfPoints(); 125 | this->Velocity.resize(numPoints*3); 126 | for(size_t pt=0;ptGridPtr->GetPoint(pt); 129 | this->Velocity[pt] = coord[1]*time; 130 | } 131 | std::fill(this->Velocity.begin()+numPoints, this->Velocity.end(), 0.); 132 | size_t numCells = this->GridPtr->GetNumberOfCells(); 133 | this->Pressure.resize(numCells); 134 | std::fill(this->Pressure.begin(), this->Pressure.end(), 1.); 135 | } 136 | 137 | double* Attributes::GetVelocityArray() 138 | { 139 | if(this->Velocity.empty()) 140 | { 141 | return NULL; 142 | } 143 | return &this->Velocity[0]; 144 | } 145 | 146 | float* Attributes::GetPressureArray() 147 | { 148 | if(this->Pressure.empty()) 149 | { 150 | return NULL; 151 | } 152 | return &this->Pressure[0]; 153 | } 154 | -------------------------------------------------------------------------------- /CxxFullExample/FEDataStructures.h: -------------------------------------------------------------------------------- 1 | #ifndef FEDATASTRUCTURES_HEADER 2 | #define FEDATASTRUCTURES_HEADER 3 | 4 | #include 5 | #include 6 | 7 | class Grid 8 | { 9 | public: 10 | Grid(); 11 | void Initialize(const unsigned int numPoints[3], const double spacing[3]); 12 | size_t GetNumberOfPoints(); 13 | size_t GetNumberOfCells(); 14 | double* GetPointsArray(); 15 | double* GetPoint(size_t pointId); 16 | unsigned int* GetCellPoints(size_t cellId); 17 | private: 18 | std::vector Points; 19 | std::vector Cells; 20 | }; 21 | 22 | class Attributes 23 | { 24 | // A class for generating and storing point and cell fields. 25 | // Velocity is stored at the points and pressure is stored 26 | // for the cells. The current velocity profile is for a 27 | // shearing flow with U(y,t) = y*t, V = 0 and W = 0. 28 | // Pressure is constant through the domain. 29 | public: 30 | Attributes(); 31 | void Initialize(Grid* grid); 32 | void UpdateFields(double time); 33 | double* GetVelocityArray(); 34 | float* GetPressureArray(); 35 | 36 | private: 37 | std::vector Velocity; 38 | std::vector Pressure; 39 | Grid* GridPtr; 40 | }; 41 | #endif 42 | -------------------------------------------------------------------------------- /CxxFullExample/FEDriver.cxx: -------------------------------------------------------------------------------- 1 | #include "FEDataStructures.h" 2 | #include 3 | 4 | #ifdef USE_CATALYST 5 | #include "FEAdaptor.h" 6 | #endif 7 | 8 | // Example of a C++ adaptor for a simulation code 9 | // where the simulation code has a fixed topology 10 | // grid. We treat the grid as an unstructured 11 | // grid even though in the example provided it 12 | // would be best described as a vtkImageData. 13 | // Also, the points are stored in an inconsistent 14 | // manner with respect to the velocity vector. 15 | // This is purposefully done to demonstrate 16 | // the different approaches for getting data 17 | // into Catalyst. Note that through configuration 18 | // that the driver can be run without linking 19 | // to Catalyst. 20 | 21 | int main(int argc, char* argv[]) 22 | { 23 | MPI_Init(&argc, &argv); 24 | Grid grid; 25 | unsigned int numPoints[3] = {70, 60, 44}; 26 | double spacing[3] = {1, 1.1, 1.3}; 27 | grid.Initialize(numPoints, spacing); 28 | Attributes attributes; 29 | attributes.Initialize(&grid); 30 | 31 | #ifdef USE_CATALYST 32 | FEAdaptor::Initialize(argc, argv); 33 | #endif 34 | unsigned int numberOfTimeSteps = 100; 35 | for(unsigned int timeStep=0;timeStep 2 | #include "FEAdaptor.h" 3 | #include "FEDataStructures.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace 19 | { 20 | vtkCPProcessor* Processor = NULL; 21 | vtkImageData* VTKGrid = NULL; 22 | 23 | void BuildVTKGrid(Grid& grid) 24 | { 25 | // The grid structure isn't changing so we only build it 26 | // the first time it's needed. If we needed the memory 27 | // we could delete it and rebuild as necessary. 28 | if(VTKGrid == NULL) 29 | { 30 | VTKGrid = vtkImageData::New(); 31 | int extent[6]; 32 | for(int i=0;i<6;i++) 33 | { 34 | extent[i] = grid.GetExtent()[i]; 35 | } 36 | VTKGrid->SetExtent(extent); 37 | VTKGrid->SetSpacing(grid.GetSpacing()); 38 | } 39 | } 40 | 41 | void UpdateVTKAttributes(Grid& grid, Attributes& attributes) 42 | { 43 | if(VTKGrid->GetPointData()->GetNumberOfArrays() == 0) 44 | { 45 | // velocity array 46 | vtkNew velocity; 47 | velocity->SetName("velocity"); 48 | velocity->SetNumberOfComponents(3); 49 | velocity->SetNumberOfTuples(static_cast(grid.GetNumberOfLocalPoints())); 50 | VTKGrid->GetPointData()->AddArray(velocity.GetPointer()); 51 | } 52 | if(VTKGrid->GetCellData()->GetNumberOfArrays() == 0) 53 | { 54 | // pressure array 55 | vtkNew pressure; 56 | pressure->SetName("pressure"); 57 | pressure->SetNumberOfComponents(1); 58 | VTKGrid->GetCellData()->AddArray(pressure.GetPointer()); 59 | } 60 | vtkDoubleArray* velocity = vtkDoubleArray::SafeDownCast( 61 | VTKGrid->GetPointData()->GetArray("velocity")); 62 | // The velocity array is ordered as vx0,vx1,vx2,..,vy0,vy1,vy2,..,vz0,vz1,vz2,.. 63 | // so we need to create a full copy of it with VTK's ordering of 64 | // vx0,vy0,vz0,vx1,vy1,vz1,.. 65 | double* velocityData = attributes.GetVelocityArray(); 66 | vtkIdType numTuples = velocity->GetNumberOfTuples(); 67 | for(vtkIdType i=0;iSetTupleValue(i, values); 72 | } 73 | 74 | vtkFloatArray* pressure = vtkFloatArray::SafeDownCast( 75 | VTKGrid->GetCellData()->GetArray("pressure")); 76 | // The pressure array is a scalar array so we can reuse 77 | // memory as long as we ordered the points properly. 78 | float* pressureData = attributes.GetPressureArray(); 79 | pressure->SetArray(pressureData, static_cast(grid.GetNumberOfLocalCells()), 1); 80 | } 81 | 82 | void BuildVTKDataStructures(Grid& grid, Attributes& attributes) 83 | { 84 | BuildVTKGrid(grid); 85 | UpdateVTKAttributes(grid, attributes); 86 | } 87 | } 88 | 89 | namespace FEAdaptor 90 | { 91 | 92 | void Initialize(int numScripts, char* scripts[]) 93 | { 94 | if(Processor == NULL) 95 | { 96 | Processor = vtkCPProcessor::New(); 97 | Processor->Initialize(); 98 | } 99 | else 100 | { 101 | Processor->RemoveAllPipelines(); 102 | } 103 | for(int i=1;i pipeline; 106 | pipeline->Initialize(scripts[i]); 107 | Processor->AddPipeline(pipeline.GetPointer()); 108 | } 109 | } 110 | 111 | void Finalize() 112 | { 113 | if(Processor) 114 | { 115 | Processor->Delete(); 116 | Processor = NULL; 117 | } 118 | if(VTKGrid) 119 | { 120 | VTKGrid->Delete(); 121 | VTKGrid = NULL; 122 | } 123 | } 124 | 125 | void CoProcess(Grid& grid, Attributes& attributes, double time, 126 | unsigned int timeStep, bool lastTimeStep) 127 | { 128 | vtkNew dataDescription; 129 | dataDescription->AddInput("input"); 130 | dataDescription->SetTimeData(time, timeStep); 131 | if(lastTimeStep == true) 132 | { 133 | // assume that we want to all the pipelines to execute if it 134 | // is the last time step. 135 | dataDescription->ForceOutputOn(); 136 | } 137 | if(Processor->RequestDataDescription(dataDescription.GetPointer()) != 0) 138 | { 139 | BuildVTKDataStructures(grid, attributes); 140 | dataDescription->GetInputDescriptionByName("input")->SetGrid(VTKGrid); 141 | int wholeExtent[6]; 142 | for(int i=0;i<6;i++) 143 | { 144 | wholeExtent[i] = grid.GetNumPoints()[i]; 145 | } 146 | 147 | dataDescription->GetInputDescriptionByName("input")->SetWholeExtent(wholeExtent); 148 | Processor->CoProcess(dataDescription.GetPointer()); 149 | } 150 | } 151 | } // end of Catalyst namespace 152 | -------------------------------------------------------------------------------- /CxxImageDataExample/FEAdaptor.h: -------------------------------------------------------------------------------- 1 | #ifndef FEADAPTOR_HEADER 2 | #define FEADAPTOR_HEADER 3 | 4 | class Attributes; 5 | class Grid; 6 | 7 | namespace FEAdaptor 8 | { 9 | void Initialize(int numScripts, char* scripts[]); 10 | 11 | void Finalize(); 12 | 13 | void CoProcess(Grid& grid, Attributes& attributes, double time, 14 | unsigned int timeStep, bool lastTimeStep); 15 | } 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /CxxImageDataExample/FEDataStructures.cxx: -------------------------------------------------------------------------------- 1 | #include "FEDataStructures.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | Grid::Grid() 8 | { 9 | this->NumPoints[0] = this->NumPoints[1] = this->NumPoints[2] = 0; 10 | this->Spacing[0] = this->Spacing[1] = this->Spacing[2] = 0; 11 | } 12 | 13 | void Grid::Initialize(const unsigned int numPoints[3], const double spacing[3] ) 14 | { 15 | if(numPoints[0] == 0 || numPoints[1] == 0 || numPoints[2] == 0) 16 | { 17 | std::cerr << "Must have a non-zero amount of points in each direction.\n"; 18 | } 19 | for(int i=0;i<3;i++) 20 | { 21 | this->NumPoints[i] = numPoints[i]; 22 | this->Spacing[i] = spacing[i]; 23 | } 24 | int mpiRank = 0, mpiSize = 1; 25 | MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); 26 | MPI_Comm_size(MPI_COMM_WORLD, &mpiSize); 27 | this->Extent[0] = mpiRank*numPoints[0]/mpiSize; 28 | this->Extent[1] = (mpiRank+1)*numPoints[0]/mpiSize; 29 | if(mpiSize != mpiRank+1) 30 | { 31 | this->Extent[1]++; 32 | } 33 | this->Extent[2] = this->Extent[4] = 0; 34 | this->Extent[3] = numPoints[1]; 35 | this->Extent[5] = numPoints[2]; 36 | } 37 | 38 | unsigned int Grid::GetNumberOfLocalPoints() 39 | { 40 | return (this->Extent[1]-this->Extent[0]+1)*(this->Extent[3]-this->Extent[2]+1)* 41 | (this->Extent[5]-this->Extent[4]+1); 42 | } 43 | 44 | unsigned int Grid::GetNumberOfLocalCells() 45 | { 46 | return (this->Extent[1]-this->Extent[0])*(this->Extent[3]-this->Extent[2])* 47 | (this->Extent[5]-this->Extent[4]); 48 | } 49 | 50 | void Grid::GetLocalPoint(unsigned int pointId, double* point) 51 | { 52 | unsigned int logicalX = pointId%(this->Extent[1]-this->Extent[0]+1); 53 | assert(logicalX <= this->Extent[1]); 54 | point[0] = this->Spacing[0]*logicalX; 55 | unsigned int logicalY = pointId%((this->Extent[1]-this->Extent[0]+1)*(this->Extent[3]-this->Extent[2]+1)); 56 | logicalY /= this->Extent[1]-this->Extent[0]+1; 57 | assert(logicalY <= this->Extent[3]); 58 | point[1] = this->Spacing[1]*logicalY; 59 | unsigned int logicalZ = pointId/((this->Extent[1]-this->Extent[0]+1)* 60 | (this->Extent[3]-this->Extent[2]+1)); 61 | assert(logicalZ <= this->Extent[5]); 62 | point[2] = this->Spacing[2]*logicalZ; 63 | } 64 | 65 | unsigned int* Grid::GetNumPoints() 66 | { 67 | return this->NumPoints; 68 | } 69 | 70 | unsigned int* Grid::GetExtent() 71 | { 72 | return this->Extent; 73 | } 74 | 75 | double* Grid::GetSpacing() 76 | { 77 | return this->Spacing; 78 | } 79 | 80 | Attributes::Attributes() 81 | { 82 | this->GridPtr = NULL; 83 | } 84 | 85 | void Attributes::Initialize(Grid* grid) 86 | { 87 | this->GridPtr = grid; 88 | } 89 | 90 | void Attributes::UpdateFields(double time) 91 | { 92 | unsigned int numPoints = this->GridPtr->GetNumberOfLocalPoints(); 93 | this->Velocity.resize(numPoints*3); 94 | for(unsigned int pt=0;ptGridPtr->GetLocalPoint(pt, coord); 98 | this->Velocity[pt] = coord[1]*time; 99 | } 100 | std::fill(this->Velocity.begin()+numPoints, this->Velocity.end(), 0.); 101 | unsigned int numCells = this->GridPtr->GetNumberOfLocalCells(); 102 | this->Pressure.resize(numCells); 103 | std::fill(this->Pressure.begin(), this->Pressure.end(), 1.); 104 | } 105 | 106 | double* Attributes::GetVelocityArray() 107 | { 108 | if(this->Velocity.empty()) 109 | { 110 | return NULL; 111 | } 112 | return &this->Velocity[0]; 113 | } 114 | 115 | float* Attributes::GetPressureArray() 116 | { 117 | if(this->Pressure.empty()) 118 | { 119 | return NULL; 120 | } 121 | return &this->Pressure[0]; 122 | } 123 | -------------------------------------------------------------------------------- /CxxImageDataExample/FEDataStructures.h: -------------------------------------------------------------------------------- 1 | #ifndef FEDATASTRUCTURES_HEADER 2 | #define FEDATASTRUCTURES_HEADER 3 | 4 | #include 5 | #include 6 | 7 | class Grid 8 | { 9 | public: 10 | Grid(); 11 | void Initialize(const unsigned int numPoints[3], const double spacing[3]); 12 | unsigned int GetNumberOfLocalPoints(); 13 | unsigned int GetNumberOfLocalCells(); 14 | void GetLocalPoint(unsigned int pointId, double* point); 15 | unsigned int* GetNumPoints(); 16 | unsigned int* GetExtent(); 17 | double* GetSpacing(); 18 | private: 19 | unsigned int NumPoints[3]; 20 | unsigned int Extent[6]; 21 | double Spacing[3]; 22 | }; 23 | 24 | class Attributes 25 | { 26 | // A class for generating and storing point and cell fields. 27 | // Velocity is stored at the points and pressure is stored 28 | // for the cells. The current velocity profile is for a 29 | // shearing flow with U(y,t) = y*t, V = 0 and W = 0. 30 | // Pressure is constant through the domain. 31 | public: 32 | Attributes(); 33 | void Initialize(Grid* grid); 34 | void UpdateFields(double time); 35 | double* GetVelocityArray(); 36 | float* GetPressureArray(); 37 | 38 | private: 39 | std::vector Velocity; 40 | std::vector Pressure; 41 | Grid* GridPtr; 42 | }; 43 | #endif 44 | -------------------------------------------------------------------------------- /CxxImageDataExample/FEDriver.cxx: -------------------------------------------------------------------------------- 1 | #include "FEDataStructures.h" 2 | #include 3 | 4 | #ifdef USE_CATALYST 5 | #include "FEAdaptor.h" 6 | #endif 7 | 8 | // Example of a C++ adaptor for a simulation code 9 | // where the simulation code has a fixed topology 10 | // grid. We treat the grid as an unstructured 11 | // grid even though in the example provided it 12 | // would be best described as a vtkImageData. 13 | // Also, the points are stored in an inconsistent 14 | // manner with respect to the velocity vector. 15 | // This is purposefully done to demonstrate 16 | // the different approaches for getting data 17 | // into Catalyst. Note that through configuration 18 | // that the driver can be run without linking 19 | // to Catalyst. 20 | 21 | int main(int argc, char* argv[]) 22 | { 23 | MPI_Init(&argc, &argv); 24 | Grid grid; 25 | unsigned int numPoints[3] = {70, 60, 44}; 26 | double spacing[3] = {1, 1.1, 1.3}; 27 | grid.Initialize(numPoints, spacing); 28 | Attributes attributes; 29 | attributes.Initialize(&grid); 30 | 31 | #ifdef USE_CATALYST 32 | FEAdaptor::Initialize(argc, argv); 33 | #endif 34 | unsigned int numberOfTimeSteps = 100; 35 | for(unsigned int timeStep=0;timeStep 2 | #include "FEAdaptor.h" 3 | #include "FEDataStructures.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "vtkCPMappedVectorArrayTemplate.h" 19 | 20 | namespace 21 | { 22 | vtkCPProcessor* Processor = NULL; 23 | vtkUnstructuredGrid* VTKGrid; 24 | 25 | void BuildVTKGrid(Grid& grid) 26 | { 27 | // create the points information 28 | vtkCPMappedVectorArrayTemplate* pointArray = 29 | vtkCPMappedVectorArrayTemplate::New(); 30 | 31 | pointArray->SetVectorArray(grid.GetPointsArray(),static_cast(grid.GetNumberOfPoints())); 32 | vtkNew points; 33 | points->SetData(pointArray); 34 | pointArray->Delete(); 35 | VTKGrid->SetPoints(points.GetPointer()); 36 | 37 | // create the cells 38 | size_t numCells = grid.GetNumberOfCells(); 39 | VTKGrid->Allocate(static_cast(numCells*9)); 40 | for(size_t cell=0;cellInsertNextCell(VTK_HEXAHEDRON, 8, tmp); 46 | } 47 | } 48 | 49 | void UpdateVTKAttributes(Grid& grid, Attributes& attributes) 50 | { 51 | if(VTKGrid->GetPointData()->GetNumberOfArrays() == 0) 52 | { 53 | // velocity array 54 | vtkCPMappedVectorArrayTemplate* velocity = 55 | vtkCPMappedVectorArrayTemplate::New(); 56 | velocity->SetName("velocity"); 57 | VTKGrid->GetPointData()->AddArray(velocity); 58 | velocity->Delete(); 59 | } 60 | vtkCPMappedVectorArrayTemplate* velocity = 61 | vtkCPMappedVectorArrayTemplate::SafeDownCast( 62 | VTKGrid->GetPointData()->GetArray("velocity")); 63 | velocity->SetVectorArray(attributes.GetVelocityArray(), 64 | VTKGrid->GetNumberOfPoints()); 65 | 66 | if(VTKGrid->GetCellData()->GetNumberOfArrays() == 0) 67 | { 68 | // pressure array 69 | vtkNew pressure; 70 | pressure->SetName("pressure"); 71 | pressure->SetNumberOfComponents(1); 72 | VTKGrid->GetCellData()->AddArray(pressure.GetPointer()); 73 | } 74 | vtkFloatArray* pressure = vtkFloatArray::SafeDownCast( 75 | VTKGrid->GetCellData()->GetArray("pressure")); 76 | // The pressure array is a scalar array so we can reuse 77 | // memory as long as we ordered the points properly. 78 | float* pressureData = attributes.GetPressureArray(); 79 | pressure->SetArray(pressureData, static_cast(grid.GetNumberOfCells()), 1); 80 | } 81 | 82 | void BuildVTKDataStructures(Grid& grid, Attributes& attributes) 83 | { 84 | if(VTKGrid == NULL) 85 | { 86 | // The grid structure isn't changing so we only build it 87 | // the first time it's needed. If we needed the memory 88 | // we could delete it and rebuild as necessary. 89 | VTKGrid = vtkUnstructuredGrid::New(); 90 | BuildVTKGrid(grid); 91 | } 92 | UpdateVTKAttributes(grid, attributes); 93 | } 94 | } 95 | 96 | namespace FEAdaptor 97 | { 98 | 99 | void Initialize(int numScripts, char* scripts[]) 100 | { 101 | if(Processor == NULL) 102 | { 103 | Processor = vtkCPProcessor::New(); 104 | Processor->Initialize(); 105 | } 106 | else 107 | { 108 | Processor->RemoveAllPipelines(); 109 | } 110 | for(int i=1;i pipeline; 113 | pipeline->Initialize(scripts[i]); 114 | Processor->AddPipeline(pipeline.GetPointer()); 115 | } 116 | } 117 | 118 | void Finalize() 119 | { 120 | if(Processor) 121 | { 122 | Processor->Delete(); 123 | Processor = NULL; 124 | } 125 | if(VTKGrid) 126 | { 127 | VTKGrid->Delete(); 128 | VTKGrid = NULL; 129 | } 130 | } 131 | 132 | void CoProcess(Grid& grid, Attributes& attributes, double time, 133 | unsigned int timeStep, bool lastTimeStep) 134 | { 135 | vtkNew dataDescription; 136 | dataDescription->AddInput("input"); 137 | dataDescription->SetTimeData(time, timeStep); 138 | if(lastTimeStep == true) 139 | { 140 | // assume that we want to all the pipelines to execute if it 141 | // is the last time step. 142 | dataDescription->ForceOutputOn(); 143 | } 144 | if(Processor->RequestDataDescription(dataDescription.GetPointer()) != 0) 145 | { 146 | BuildVTKDataStructures(grid, attributes); 147 | dataDescription->GetInputDescriptionByName("input")->SetGrid(VTKGrid); 148 | Processor->CoProcess(dataDescription.GetPointer()); 149 | } 150 | } 151 | } // end of Catalyst namespace 152 | -------------------------------------------------------------------------------- /CxxMappedDataArrayExample/FEAdaptor.h: -------------------------------------------------------------------------------- 1 | #ifndef FEADAPTOR_HEADER 2 | #define FEADAPTOR_HEADER 3 | 4 | class Attributes; 5 | class Grid; 6 | 7 | namespace FEAdaptor 8 | { 9 | void Initialize(int numScripts, char* scripts[]); 10 | 11 | void Finalize(); 12 | 13 | void CoProcess(Grid& grid, Attributes& attributes, double time, 14 | unsigned int timeStep, bool lastTimeStep); 15 | } 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /CxxMappedDataArrayExample/FEDataStructures.cxx: -------------------------------------------------------------------------------- 1 | #include "FEDataStructures.h" 2 | 3 | #include 4 | #include 5 | 6 | Grid::Grid() 7 | {} 8 | 9 | void Grid::Initialize(const unsigned int numPoints[3], const double spacing[3] ) 10 | { 11 | if(numPoints[0] == 0 || numPoints[1] == 0 || numPoints[2] == 0) 12 | { 13 | std::cerr << "Must have a non-zero amount of points in each direction.\n"; 14 | } 15 | // in parallel, we do a simple partitioning in the x-direction. 16 | int mpiSize = 1; 17 | int mpiRank = 0; 18 | MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); 19 | MPI_Comm_size(MPI_COMM_WORLD, &mpiSize); 20 | 21 | unsigned int startXPoint = mpiRank*numPoints[0]/mpiSize; 22 | unsigned int endXPoint = (mpiRank+1)*numPoints[0]/mpiSize; 23 | if(mpiSize != mpiRank+1) 24 | { 25 | endXPoint++; 26 | } 27 | 28 | // create the points -- slowest in the x and fastest in the z directions 29 | // all of the x coordinates are stored first, then y coordinates and 30 | // finally z coordinates (e.g. x[0], x[1], ..., x[n-1], y[0], y[1], ..., 31 | // y[n-1], z[0], z[1], ..., z[n-1]) which is OPPOSITE of VTK's ordering. 32 | size_t numTotalPoints = (endXPoint-startXPoint)*numPoints[1]*numPoints[2]; 33 | this->Points.resize(3*numTotalPoints); 34 | size_t counter = 0; 35 | for(unsigned int i=startXPoint;iPoints[counter] = i*spacing[0]; 42 | this->Points[numTotalPoints+counter] = j*spacing[1]; 43 | this->Points[2*numTotalPoints+counter] = k*spacing[2]; 44 | counter++; 45 | } 46 | } 47 | } 48 | 49 | // create the hex cells 50 | unsigned int cellPoints[8]; 51 | unsigned int numXPoints = endXPoint - startXPoint; 52 | for(unsigned int i=0;iCells)); 75 | } 76 | } 77 | } 78 | } 79 | 80 | size_t Grid::GetNumberOfPoints() 81 | { 82 | return this->Points.size()/3; 83 | } 84 | 85 | size_t Grid::GetNumberOfCells() 86 | { 87 | return this->Cells.size()/8; 88 | } 89 | 90 | double* Grid::GetPointsArray() 91 | { 92 | if(this->Points.empty()) 93 | { 94 | return NULL; 95 | } 96 | return &(this->Points[0]); 97 | } 98 | 99 | bool Grid::GetPoint(size_t pointId, double coord[3]) 100 | { 101 | if(pointId >= this->Points.size()/3) 102 | { 103 | return false; 104 | } 105 | coord[0] = this->Points[pointId]; 106 | coord[1] = this->Points[pointId+this->GetNumberOfPoints()]; 107 | coord[2] = this->Points[pointId+2*this->GetNumberOfPoints()]; 108 | return true; 109 | } 110 | 111 | unsigned int* Grid::GetCellPoints(size_t cellId) 112 | { 113 | if(cellId >= this->Cells.size()) 114 | { 115 | return NULL; 116 | } 117 | return &(this->Cells[cellId*8]); 118 | } 119 | 120 | Attributes::Attributes() 121 | { 122 | this->GridPtr = NULL; 123 | } 124 | 125 | void Attributes::Initialize(Grid* grid) 126 | { 127 | this->GridPtr = grid; 128 | } 129 | 130 | void Attributes::UpdateFields(double time) 131 | { 132 | size_t numPoints = this->GridPtr->GetNumberOfPoints(); 133 | this->Velocity.resize(numPoints*3); 134 | double coord[3] = {0, 0, 0}; 135 | for(size_t pt=0;ptGridPtr->GetPoint(pt, coord); 138 | this->Velocity[pt] = coord[1]*time; 139 | } 140 | std::fill(this->Velocity.begin()+numPoints, this->Velocity.end(), 0.); 141 | size_t numCells = this->GridPtr->GetNumberOfCells(); 142 | this->Pressure.resize(numCells); 143 | std::fill(this->Pressure.begin(), this->Pressure.end(), 1.); 144 | } 145 | 146 | double* Attributes::GetVelocityArray() 147 | { 148 | if(this->Velocity.empty()) 149 | { 150 | return NULL; 151 | } 152 | return &this->Velocity[0]; 153 | } 154 | 155 | float* Attributes::GetPressureArray() 156 | { 157 | if(this->Pressure.empty()) 158 | { 159 | return NULL; 160 | } 161 | return &this->Pressure[0]; 162 | } 163 | -------------------------------------------------------------------------------- /CxxMappedDataArrayExample/FEDataStructures.h: -------------------------------------------------------------------------------- 1 | #ifndef FEDATASTRUCTURES_HEADER 2 | #define FEDATASTRUCTURES_HEADER 3 | 4 | #include 5 | #include 6 | 7 | class Grid 8 | { 9 | public: 10 | Grid(); 11 | void Initialize(const unsigned int numPoints[3], const double spacing[3]); 12 | size_t GetNumberOfPoints(); 13 | size_t GetNumberOfCells(); 14 | double* GetPointsArray(); 15 | bool GetPoint(size_t pointId, double coord[3]); 16 | unsigned int* GetCellPoints(size_t cellId); 17 | private: 18 | std::vector Points; 19 | std::vector Cells; 20 | }; 21 | 22 | class Attributes 23 | { 24 | // A class for generating and storing point and cell fields. 25 | // Velocity is stored at the points and pressure is stored 26 | // for the cells. The current velocity profile is for a 27 | // shearing flow with U(y,t) = y*t, V = 0 and W = 0. 28 | // Pressure is constant through the domain. 29 | public: 30 | Attributes(); 31 | void Initialize(Grid* grid); 32 | void UpdateFields(double time); 33 | double* GetVelocityArray(); 34 | float* GetPressureArray(); 35 | 36 | private: 37 | std::vector Velocity; 38 | std::vector Pressure; 39 | Grid* GridPtr; 40 | }; 41 | #endif 42 | -------------------------------------------------------------------------------- /CxxMappedDataArrayExample/FEDriver.cxx: -------------------------------------------------------------------------------- 1 | #include "FEDataStructures.h" 2 | #include 3 | 4 | #ifdef USE_CATALYST 5 | #include "FEAdaptor.h" 6 | #endif 7 | 8 | // Example of a C++ adaptor for a simulation code 9 | // where the simulation code has a fixed topology 10 | // grid. We treat the grid as an unstructured 11 | // grid even though in the example provided it 12 | // would be best described as a vtkImageData. 13 | // Also, the points are stored in an inconsistent 14 | // manner with respect to the velocity vector. 15 | // This is purposefully done to demonstrate 16 | // the different approaches for getting data 17 | // into Catalyst. Note that through configuration 18 | // that the driver can be run without linking 19 | // to Catalyst. 20 | 21 | int main(int argc, char* argv[]) 22 | { 23 | MPI_Init(&argc, &argv); 24 | Grid grid; 25 | unsigned int numPoints[3] = {70, 60, 44}; 26 | double spacing[3] = {1, 1.1, 1.3}; 27 | grid.Initialize(numPoints, spacing); 28 | Attributes attributes; 29 | attributes.Initialize(&grid); 30 | 31 | #ifdef USE_CATALYST 32 | FEAdaptor::Initialize(argc, argv); 33 | #endif 34 | unsigned int numberOfTimeSteps = 100; 35 | for(unsigned int timeStep=0;timeStep 32 | class vtkCPMappedVectorArrayTemplate: 33 | public vtkTypeTemplate, 34 | vtkMappedDataArray > 35 | { 36 | public: 37 | vtkMappedDataArrayNewInstanceMacro( 38 | vtkCPMappedVectorArrayTemplate) 39 | static vtkCPMappedVectorArrayTemplate *New(); 40 | virtual void PrintSelf(ostream &os, vtkIndent indent); 41 | 42 | // Description: 43 | // Set the raw scalar arrays for the coordinate set. This class takes 44 | // ownership of the arrays and deletes them with delete[]. 45 | void SetVectorArray(Scalar *array, vtkIdType numPoints); 46 | 47 | // Reimplemented virtuals -- see superclasses for descriptions: 48 | void Initialize(); 49 | void GetTuples(vtkIdList *ptIds, vtkAbstractArray *output); 50 | void GetTuples(vtkIdType p1, vtkIdType p2, vtkAbstractArray *output); 51 | void Squeeze(); 52 | vtkArrayIterator *NewIterator(); 53 | vtkIdType LookupValue(vtkVariant value); 54 | void LookupValue(vtkVariant value, vtkIdList *ids); 55 | vtkVariant GetVariantValue(vtkIdType idx); 56 | void ClearLookup(); 57 | double* GetTuple(vtkIdType i); 58 | void GetTuple(vtkIdType i, double *tuple); 59 | vtkIdType LookupTypedValue(Scalar value); 60 | void LookupTypedValue(Scalar value, vtkIdList *ids); 61 | Scalar GetValue(vtkIdType idx); 62 | Scalar& GetValueReference(vtkIdType idx); 63 | void GetTupleValue(vtkIdType idx, Scalar *t); 64 | 65 | // Description: 66 | // This container is read only -- this method does nothing but print a 67 | // warning. 68 | int Allocate(vtkIdType sz, vtkIdType ext); 69 | int Resize(vtkIdType numTuples); 70 | void SetNumberOfTuples(vtkIdType number); 71 | void SetTuple(vtkIdType i, vtkIdType j, vtkAbstractArray *source); 72 | void SetTuple(vtkIdType i, const float *source); 73 | void SetTuple(vtkIdType i, const double *source); 74 | void InsertTuple(vtkIdType i, vtkIdType j, vtkAbstractArray *source); 75 | void InsertTuple(vtkIdType i, const float *source); 76 | void InsertTuple(vtkIdType i, const double *source); 77 | void InsertTuples(vtkIdList *dstIds, vtkIdList *srcIds, 78 | vtkAbstractArray *source); 79 | void InsertTuples(vtkIdType dstStart, vtkIdType n, vtkIdType srcStart, 80 | vtkAbstractArray* source); 81 | vtkIdType InsertNextTuple(vtkIdType j, vtkAbstractArray *source); 82 | vtkIdType InsertNextTuple(const float *source); 83 | vtkIdType InsertNextTuple(const double *source); 84 | void DeepCopy(vtkAbstractArray *aa); 85 | void DeepCopy(vtkDataArray *da); 86 | void InterpolateTuple(vtkIdType i, vtkIdList *ptIndices, 87 | vtkAbstractArray* source, double* weights); 88 | void InterpolateTuple(vtkIdType i, vtkIdType id1, vtkAbstractArray *source1, 89 | vtkIdType id2, vtkAbstractArray *source2, double t); 90 | void SetVariantValue(vtkIdType idx, vtkVariant value); 91 | void InsertVariantValue(vtkIdType idx, vtkVariant value); 92 | void RemoveTuple(vtkIdType id); 93 | void RemoveFirstTuple(); 94 | void RemoveLastTuple(); 95 | void SetTupleValue(vtkIdType i, const Scalar *t); 96 | void InsertTupleValue(vtkIdType i, const Scalar *t); 97 | vtkIdType InsertNextTupleValue(const Scalar *t); 98 | void SetValue(vtkIdType idx, Scalar value); 99 | vtkIdType InsertNextValue(Scalar v); 100 | void InsertValue(vtkIdType idx, Scalar v); 101 | 102 | protected: 103 | vtkCPMappedVectorArrayTemplate(); 104 | ~vtkCPMappedVectorArrayTemplate(); 105 | 106 | Scalar *Array; 107 | 108 | private: 109 | vtkCPMappedVectorArrayTemplate( 110 | const vtkCPMappedVectorArrayTemplate &); // Not implemented. 111 | void operator=( 112 | const vtkCPMappedVectorArrayTemplate &); // Not implemented. 113 | 114 | vtkIdType Lookup(const Scalar &val, vtkIdType startIndex); 115 | double TempDoubleArray[3]; 116 | }; 117 | 118 | #include "vtkCPMappedVectorArrayTemplate.txx" 119 | 120 | #endif //__vtkCPMappedVectorArrayTemplate_h 121 | -------------------------------------------------------------------------------- /CxxMultiPieceExample/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.8) 2 | project(CatalystCxxMultiPieceExample) 3 | 4 | set(USE_CATALYST ON CACHE BOOL "Link the simulator with Catalyst") 5 | if(USE_CATALYST) 6 | find_package(ParaView 4.1 REQUIRED COMPONENTS vtkPVPythonCatalyst) 7 | include("${PARAVIEW_USE_FILE}") 8 | set(Adaptor_SRCS 9 | FEAdaptor.cxx 10 | ) 11 | add_library(CxxMultiPieceExampleAdaptor ${Adaptor_SRCS}) 12 | target_link_libraries(CxxMultiPieceExampleAdaptor vtkPVPythonCatalyst) 13 | add_definitions("-DUSE_CATALYST") 14 | if(NOT PARAVIEW_USE_MPI) 15 | message(SEND_ERROR "ParaView must be built with MPI enabled") 16 | endif() 17 | else() 18 | find_package(MPI REQUIRED) 19 | include_directories(${MPI_CXX_INCLUDE_PATH}) 20 | endif() 21 | 22 | add_executable(CxxMultiPieceExample FEDriver.cxx FEDataStructures.cxx) 23 | if(USE_CATALYST) 24 | target_link_libraries(CxxMultiPieceExample LINK_PRIVATE CxxMultiPieceExampleAdaptor) 25 | include(vtkModuleMacros) 26 | include(vtkMPI) 27 | vtk_mpi_link(CxxMultiPieceExample) 28 | else() 29 | target_link_libraries(CxxMultiPieceExample LINK_PRIVATE ${MPI_LIBRARIES}) 30 | endif() 31 | 32 | option(BUILD_TESTING "Build Testing" OFF) 33 | # Setup testing. 34 | if (BUILD_TESTING) 35 | include(CTest) 36 | add_test(CxxMultiPieceExampleTest CxxMultiPieceExample ${CMAKE_CURRENT_SOURCE_DIR}/SampleScripts/feslicescript.py) 37 | endif() 38 | -------------------------------------------------------------------------------- /CxxMultiPieceExample/FEAdaptor.h: -------------------------------------------------------------------------------- 1 | #ifndef FEADAPTOR_HEADER 2 | #define FEADAPTOR_HEADER 3 | 4 | class Attributes; 5 | class Grid; 6 | 7 | namespace FEAdaptor 8 | { 9 | void Initialize(int numScripts, char* scripts[]); 10 | 11 | void Finalize(); 12 | 13 | void CoProcess(Grid& grid, Attributes& attributes, double time, 14 | unsigned int timeStep, bool lastTimeStep); 15 | } 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /CxxMultiPieceExample/FEDataStructures.cxx: -------------------------------------------------------------------------------- 1 | #include "FEDataStructures.h" 2 | 3 | #include 4 | #include 5 | 6 | Grid::Grid() 7 | {} 8 | 9 | void Grid::Initialize(const unsigned int numPoints[3], const double spacing[3] ) 10 | { 11 | if(numPoints[0] == 0 || numPoints[1] == 0 || numPoints[2] == 0) 12 | { 13 | std::cerr << "Must have a non-zero amount of points in each direction.\n"; 14 | } 15 | for(int i=0;i<3;i++) 16 | { 17 | this->Extents[i*2] = 0; 18 | this->Extents[i*2+1] = numPoints[i]; 19 | this->Spacing[i] = spacing[i]; 20 | } 21 | 22 | // in parallel, we do a simple partitioning in the x-direction. 23 | int mpiSize = 1; 24 | int mpiRank = 0; 25 | MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); 26 | MPI_Comm_size(MPI_COMM_WORLD, &mpiSize); 27 | 28 | this->Extents[0] = mpiRank*numPoints[0]/mpiSize; 29 | this->Extents[1] = (mpiRank+1)*numPoints[0]/mpiSize; 30 | } 31 | 32 | unsigned int Grid::GetNumberOfLocalPoints() 33 | { 34 | return (this->Extents[1]-this->Extents[0]+1) * 35 | (this->Extents[3]-this->Extents[2]+1) * 36 | (this->Extents[5]-this->Extents[4]+1); 37 | } 38 | 39 | unsigned int Grid::GetNumberOfLocalCells() 40 | { 41 | return (this->Extents[1]-this->Extents[0]) * 42 | (this->Extents[3]-this->Extents[2]) * 43 | (this->Extents[5]-this->Extents[4]); 44 | } 45 | 46 | void Grid::GetPoint(unsigned int logicalLocalCoords[3], double coord[3]) 47 | { 48 | coord[0] = (this->Extents[0]+logicalLocalCoords[0])*this->Spacing[0]; 49 | coord[1] = logicalLocalCoords[1]*this->Spacing[1]; 50 | coord[2] = logicalLocalCoords[2]*this->Spacing[2]; 51 | } 52 | 53 | double* Grid::GetSpacing() 54 | { 55 | return this->Spacing; 56 | } 57 | 58 | unsigned int* Grid::GetExtents() 59 | { 60 | return this->Extents; 61 | } 62 | 63 | Attributes::Attributes() 64 | { 65 | this->GridPtr = NULL; 66 | } 67 | 68 | void Attributes::Initialize(Grid* grid) 69 | { 70 | this->GridPtr = grid; 71 | } 72 | 73 | void Attributes::UpdateFields(double time) 74 | { 75 | size_t numPoints = this->GridPtr->GetNumberOfLocalPoints(); 76 | this->Velocity.resize(numPoints*3); 77 | unsigned int* extents = this->GridPtr->GetExtents(); 78 | unsigned int logicalLocalCoords[3]; 79 | size_t pt = 0; 80 | for(unsigned int k=0;kGridPtr->GetPoint(logicalLocalCoords, coord); 91 | this->Velocity[pt] = coord[1]*time; 92 | pt++; 93 | } 94 | } 95 | } 96 | std::fill(this->Velocity.begin()+numPoints, this->Velocity.end(), 0.); 97 | size_t numCells = this->GridPtr->GetNumberOfLocalCells(); 98 | this->Pressure.resize(numCells); 99 | std::fill(this->Pressure.begin(), this->Pressure.end(), 1.); 100 | } 101 | 102 | double* Attributes::GetVelocityArray() 103 | { 104 | if(this->Velocity.empty()) 105 | { 106 | return NULL; 107 | } 108 | return &this->Velocity[0]; 109 | } 110 | 111 | float* Attributes::GetPressureArray() 112 | { 113 | if(this->Pressure.empty()) 114 | { 115 | return NULL; 116 | } 117 | return &this->Pressure[0]; 118 | } 119 | -------------------------------------------------------------------------------- /CxxMultiPieceExample/FEDataStructures.h: -------------------------------------------------------------------------------- 1 | #ifndef FEDATASTRUCTURES_HEADER 2 | #define FEDATASTRUCTURES_HEADER 3 | 4 | #include 5 | #include 6 | 7 | class Grid 8 | { 9 | public: 10 | Grid(); 11 | void Initialize(const unsigned int numGlobalPoints[3], const double spacing[3]); 12 | unsigned int GetNumberOfLocalPoints(); 13 | unsigned int GetNumberOfLocalCells(); 14 | void GetPoint(unsigned int logicalLocalCoords[3], double coord[3]); 15 | double* GetSpacing(); 16 | unsigned int* GetExtents(); 17 | private: 18 | unsigned int Extents[6]; 19 | double Spacing[3]; 20 | }; 21 | 22 | class Attributes 23 | { 24 | // A class for generating and storing point and cell fields. 25 | // Velocity is stored at the points and pressure is stored 26 | // for the cells. The current velocity profile is for a 27 | // shearing flow with U(y,t) = y*t, V = 0 and W = 0. 28 | // Pressure is constant through the domain. 29 | public: 30 | Attributes(); 31 | void Initialize(Grid* grid); 32 | void UpdateFields(double time); 33 | double* GetVelocityArray(); 34 | float* GetPressureArray(); 35 | 36 | private: 37 | std::vector Velocity; 38 | std::vector Pressure; 39 | Grid* GridPtr; 40 | }; 41 | #endif 42 | -------------------------------------------------------------------------------- /CxxMultiPieceExample/FEDriver.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include "FEDataStructures.h" 3 | #include 4 | #include 5 | #include 6 | 7 | #ifdef USE_CATALYST 8 | #include "FEAdaptor.h" 9 | #endif 10 | 11 | // Example of a C++ adaptor for a simulation code 12 | // where the simulation code has a fixed topology 13 | // grid. We treat the grid as a partitioned 14 | // regular grid. This is stored as a set of 15 | // vtkImageDatas in a vtkMultiPieceDataSet. 16 | // Also, the points are stored in an inconsistent 17 | // manner with respect to the velocity vector. 18 | // This is purposefully done to demonstrate 19 | // the different approaches for getting data 20 | // into Catalyst. Note that through configuration 21 | // that the driver can be run without linking 22 | // to Catalyst. 23 | 24 | int main(int argc, char* argv[]) 25 | { 26 | MPI_Init(&argc, &argv); 27 | Grid grid; 28 | unsigned int numPoints[3] = {70, 60, 44}; 29 | double spacing[3] = {1, 1.1, 1.3}; 30 | grid.Initialize(numPoints, spacing); 31 | Attributes attributes; 32 | attributes.Initialize(&grid); 33 | 34 | #ifdef USE_CATALYST 35 | FEAdaptor::Initialize(argc, argv); 36 | #endif 37 | unsigned int numberOfTimeSteps = 100; 38 | for(unsigned int timeStep=0;timeStep 2 | #include "FEAdaptor.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace 14 | { 15 | vtkCPProcessor* Processor = NULL; 16 | vtkNonOverlappingAMR* VTKGrid; 17 | 18 | void BuildVTKGrid() 19 | { 20 | if(VTKGrid == NULL) 21 | { 22 | // The grid structure isn't changing so we only build it 23 | // the first time it's needed. If we needed the memory 24 | // we could delete it and rebuild as necessary. 25 | VTKGrid = vtkNonOverlappingAMR::New(); 26 | } 27 | 28 | // Note that all of the vtkUniformGrids in the vtkNonOverlappingAMR 29 | // grid can use independent spacing, origin and extents. This is 30 | // shown in the mid-level grids in that they don't share an 31 | // origin. The highest level grid and lowest level grid do share 32 | // the same origin of (0,0,0) and thus need to have appropriate 33 | // extents and spacings as well. 34 | int numberOfLevels = 3; 35 | int blocksPerLevel[3] = {1, 2, 1}; 36 | VTKGrid->Initialize(numberOfLevels, blocksPerLevel); 37 | 38 | // the highest level grid 39 | vtkNew level0Grid; 40 | level0Grid->SetSpacing(4, 4, 4); 41 | level0Grid->SetOrigin(0, 0, 0); 42 | level0Grid->SetExtent(0, 10, 0, 20, 0, 20); 43 | VTKGrid->SetDataSet(0, 0, level0Grid.GetPointer()); 44 | 45 | // the first mid-level grid 46 | vtkNew level1Grid0; 47 | level1Grid0->SetSpacing(2, 2, 2); 48 | level1Grid0->SetOrigin(40, 0, 0); 49 | level1Grid0->SetExtent(0, 8, 0, 20, 0, 40); 50 | VTKGrid->SetDataSet(1, 0, level1Grid0.GetPointer()); 51 | 52 | // the second mid-level grid 53 | vtkNew level1Grid1; 54 | level1Grid1->SetSpacing(2, 2, 2); 55 | level1Grid1->SetOrigin(40, 40, 0); 56 | level1Grid1->SetExtent(0, 40, 0, 20, 0, 40); 57 | VTKGrid->SetDataSet(1, 1, level1Grid1.GetPointer()); 58 | 59 | // the lowest level grid 60 | vtkNew level2Grid; 61 | level2Grid->SetSpacing(1, 1, 2); 62 | level2Grid->SetOrigin(0, 0, 0); 63 | level2Grid->SetExtent(56, 120, 0, 40, 0, 40); 64 | VTKGrid->SetDataSet(2, 0, level2Grid.GetPointer()); 65 | } 66 | } 67 | 68 | namespace FEAdaptor 69 | { 70 | void Initialize(int numScripts, char* scripts[]) 71 | { 72 | if(Processor == NULL) 73 | { 74 | Processor = vtkCPProcessor::New(); 75 | Processor->Initialize(); 76 | } 77 | else 78 | { 79 | Processor->RemoveAllPipelines(); 80 | } 81 | for(int i=1;i pipeline; 84 | pipeline->Initialize(scripts[i]); 85 | Processor->AddPipeline(pipeline.GetPointer()); 86 | } 87 | } 88 | 89 | void Finalize() 90 | { 91 | if(Processor) 92 | { 93 | Processor->Delete(); 94 | Processor = NULL; 95 | } 96 | if(VTKGrid) 97 | { 98 | VTKGrid->Delete(); 99 | VTKGrid = NULL; 100 | } 101 | } 102 | 103 | void CoProcess(double time, unsigned int timeStep, bool lastTimeStep) 104 | { 105 | vtkNew dataDescription; 106 | dataDescription->AddInput("input"); 107 | dataDescription->SetTimeData(time, timeStep); 108 | if(lastTimeStep == true) 109 | { 110 | // assume that we want to all the pipelines to execute if it 111 | // is the last time step. 112 | dataDescription->ForceOutputOn(); 113 | } 114 | if(Processor->RequestDataDescription(dataDescription.GetPointer()) != 0) 115 | { 116 | BuildVTKGrid(); 117 | dataDescription->GetInputDescriptionByName("input")->SetGrid(VTKGrid); 118 | Processor->CoProcess(dataDescription.GetPointer()); 119 | } 120 | } 121 | } // end of Catalyst namespace 122 | -------------------------------------------------------------------------------- /CxxNonOverlappingAMRExample/FEAdaptor.h: -------------------------------------------------------------------------------- 1 | #ifndef FEADAPTOR_HEADER 2 | #define FEADAPTOR_HEADER 3 | 4 | namespace FEAdaptor 5 | { 6 | void Initialize(int numScripts, char* scripts[]); 7 | 8 | void Finalize(); 9 | 10 | void CoProcess(double time, unsigned int timeStep, bool lastTimeStep); 11 | } 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /CxxNonOverlappingAMRExample/FEDriver.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "FEAdaptor.h" 5 | 6 | // Example of a C++ adaptor for a simulation code 7 | // where the simulation code has a fixed topology 8 | // grid. The grid in this case is a vtkNonOverlappingAMR 9 | // data set without any attributes specified 10 | // over the grid. 11 | 12 | int main(int argc, char* argv[]) 13 | { 14 | FEAdaptor::Initialize(argc, argv); 15 | unsigned int numberOfTimeSteps = 100; 16 | for(unsigned int timeStep=0;timeStep 2 | #include "FEAdaptor.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace 15 | { 16 | vtkCPProcessor* Processor = NULL; 17 | vtkOverlappingAMR* VTKGrid; 18 | 19 | void BuildVTKGrid() 20 | { 21 | if(VTKGrid == NULL) 22 | { 23 | // The grid structure isn't changing so we only build it 24 | // the first time it's needed. If we needed the memory 25 | // we could delete it and rebuild as necessary. 26 | VTKGrid = vtkOverlappingAMR::New(); 27 | BuildVTKGrid(); 28 | } 29 | 30 | int numberOfLevels = 3; 31 | int blocksPerLevel[3] = {1, 1, 1}; 32 | VTKGrid->Initialize(numberOfLevels, blocksPerLevel); 33 | VTKGrid->SetGridDescription(VTK_XYZ_GRID); 34 | double origin[] = {0,0,0}; 35 | double level0Spacing[] = {4, 4, 4}; 36 | double level1Spacing[] = {2, 2, 2}; 37 | double level2Spacing[] = {1, 1, 1}; 38 | VTKGrid->SetOrigin(origin); 39 | int level0Dims[] = {25, 25, 25}; 40 | vtkAMRBox level0Box(origin, level0Dims, level0Spacing, origin, VTK_XYZ_GRID); 41 | int level1Dims[] = {20, 20, 20}; 42 | vtkAMRBox level1Box(origin, level1Dims, level1Spacing, origin, VTK_XYZ_GRID); 43 | int level2Dims[] = {10, 10, 10}; 44 | vtkAMRBox level2Box(origin, level2Dims, level2Spacing, origin, VTK_XYZ_GRID); 45 | VTKGrid->SetSpacing(0, level0Spacing); 46 | VTKGrid->SetAMRBox(0, 0, level0Box); 47 | 48 | VTKGrid->SetSpacing(1, level1Spacing); 49 | VTKGrid->SetAMRBox(1, 0, level1Box); 50 | 51 | VTKGrid->SetSpacing(2, level2Spacing); 52 | VTKGrid->SetAMRBox(2, 0, level2Box); 53 | 54 | VTKGrid->GenerateParentChildInformation(); 55 | 56 | // the highest level grid 57 | vtkNew level0Grid; 58 | level0Grid->SetSpacing(level0Spacing); 59 | level0Grid->SetOrigin(0, 0, 0); 60 | level0Grid->SetExtent(0, 25, 0, 25, 0, 25); 61 | VTKGrid->SetDataSet(0, 0, level0Grid.GetPointer()); 62 | 63 | // the mid-level grid 64 | vtkNew level1Grid0; 65 | level1Grid0->SetSpacing(level1Spacing); 66 | level1Grid0->SetExtent(0, 20, 0, 20, 0, 20); 67 | VTKGrid->SetDataSet(1, 0, level1Grid0.GetPointer()); 68 | 69 | // the lowest level grid 70 | vtkNew level2Grid; 71 | level2Grid->SetSpacing(level2Spacing); 72 | level2Grid->SetExtent(0, 10, 0, 10, 0, 10); 73 | VTKGrid->SetDataSet(2, 0, level2Grid.GetPointer()); 74 | 75 | } 76 | } 77 | 78 | namespace FEAdaptor 79 | { 80 | void Initialize(int numScripts, char* scripts[]) 81 | { 82 | if(Processor == NULL) 83 | { 84 | Processor = vtkCPProcessor::New(); 85 | Processor->Initialize(); 86 | } 87 | else 88 | { 89 | Processor->RemoveAllPipelines(); 90 | } 91 | for(int i=1;i pipeline; 94 | pipeline->Initialize(scripts[i]); 95 | Processor->AddPipeline(pipeline.GetPointer()); 96 | } 97 | } 98 | 99 | void Finalize() 100 | { 101 | if(Processor) 102 | { 103 | Processor->Delete(); 104 | Processor = NULL; 105 | } 106 | if(VTKGrid) 107 | { 108 | VTKGrid->Delete(); 109 | VTKGrid = NULL; 110 | } 111 | } 112 | 113 | void CoProcess(double time, unsigned int timeStep, bool lastTimeStep) 114 | { 115 | vtkNew dataDescription; 116 | dataDescription->AddInput("input"); 117 | dataDescription->SetTimeData(time, timeStep); 118 | if(lastTimeStep == true) 119 | { 120 | // assume that we want to all the pipelines to execute if it 121 | // is the last time step. 122 | dataDescription->ForceOutputOn(); 123 | } 124 | if(Processor->RequestDataDescription(dataDescription.GetPointer()) != 0) 125 | { 126 | BuildVTKGrid(); 127 | dataDescription->GetInputDescriptionByName("input")->SetGrid(VTKGrid); 128 | Processor->CoProcess(dataDescription.GetPointer()); 129 | } 130 | } 131 | } // end of Catalyst namespace 132 | -------------------------------------------------------------------------------- /CxxOverlappingAMRExample/FEAdaptor.h: -------------------------------------------------------------------------------- 1 | #ifndef FEADAPTOR_HEADER 2 | #define FEADAPTOR_HEADER 3 | 4 | namespace FEAdaptor 5 | { 6 | void Initialize(int numScripts, char* scripts[]); 7 | 8 | void Finalize(); 9 | 10 | void CoProcess(double time, unsigned int timeStep, bool lastTimeStep); 11 | } 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /CxxOverlappingAMRExample/FEDriver.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "FEAdaptor.h" 5 | 6 | // Example of a C++ adaptor for a simulation code 7 | // where the simulation code has a fixed topology 8 | // grid. The grid in this case is a vtkOverlappingAMR 9 | // data set without any attributes specified 10 | // over the grid. 11 | 12 | int main(int argc, char* argv[]) 13 | { 14 | FEAdaptor::Initialize(argc, argv); 15 | unsigned int numberOfTimeSteps = 100; 16 | for(unsigned int timeStep=0;timeStep 5 | 6 | class Attributes; 7 | class Grid; 8 | 9 | namespace FEAdaptor 10 | { 11 | void Initialize(int outputFrequency, std::string fileName); 12 | 13 | void Finalize(); 14 | 15 | void CoProcess(Grid& grid, Attributes& attributes, double time, 16 | unsigned int timeStep, bool lastTimeStep); 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /CxxPVSMPipelineExample/FEDataStructures.cxx: -------------------------------------------------------------------------------- 1 | #include "FEDataStructures.h" 2 | 3 | #include 4 | #include 5 | 6 | Grid::Grid() 7 | {} 8 | 9 | void Grid::Initialize(const unsigned int numPoints[3], const double spacing[3] ) 10 | { 11 | if(numPoints[0] == 0 || numPoints[1] == 0 || numPoints[2] == 0) 12 | { 13 | std::cerr << "Must have a non-zero amount of points in each direction.\n"; 14 | } 15 | // in parallel, we do a simple partitioning in the x-direction. 16 | int mpiSize = 1; 17 | int mpiRank = 0; 18 | MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); 19 | MPI_Comm_size(MPI_COMM_WORLD, &mpiSize); 20 | 21 | unsigned int startXPoint = mpiRank*numPoints[0]/mpiSize; 22 | unsigned int endXPoint = (mpiRank+1)*numPoints[0]/mpiSize; 23 | if(mpiSize != mpiRank+1) 24 | { 25 | endXPoint++; 26 | } 27 | 28 | // create the points -- slowest in the x and fastest in the z directions 29 | double coord[3] = {0,0,0}; 30 | for(unsigned int i=startXPoint;iPoints)); 41 | } 42 | } 43 | } 44 | // create the hex cells 45 | unsigned int cellPoints[8]; 46 | unsigned int numXPoints = endXPoint - startXPoint; 47 | for(unsigned int i=0;iCells)); 70 | } 71 | } 72 | } 73 | } 74 | 75 | size_t Grid::GetNumberOfPoints() 76 | { 77 | return this->Points.size()/3; 78 | } 79 | 80 | size_t Grid::GetNumberOfCells() 81 | { 82 | return this->Cells.size()/8; 83 | } 84 | 85 | double* Grid::GetPointsArray() 86 | { 87 | if(this->Points.empty()) 88 | { 89 | return NULL; 90 | } 91 | return &(this->Points[0]); 92 | } 93 | 94 | double* Grid::GetPoint(size_t pointId) 95 | { 96 | if(pointId >= this->Points.size()) 97 | { 98 | return NULL; 99 | } 100 | return &(this->Points[pointId*3]); 101 | } 102 | 103 | unsigned int* Grid::GetCellPoints(size_t cellId) 104 | { 105 | if(cellId >= this->Cells.size()) 106 | { 107 | return NULL; 108 | } 109 | return &(this->Cells[cellId*8]); 110 | } 111 | 112 | Attributes::Attributes() 113 | { 114 | this->GridPtr = NULL; 115 | } 116 | 117 | void Attributes::Initialize(Grid* grid) 118 | { 119 | this->GridPtr = grid; 120 | } 121 | 122 | void Attributes::UpdateFields(double time) 123 | { 124 | size_t numPoints = this->GridPtr->GetNumberOfPoints(); 125 | this->Velocity.resize(numPoints*3); 126 | for(size_t pt=0;ptGridPtr->GetPoint(pt); 129 | this->Velocity[pt] = coord[1]*time; 130 | } 131 | std::fill(this->Velocity.begin()+numPoints, this->Velocity.end(), 0.); 132 | size_t numCells = this->GridPtr->GetNumberOfCells(); 133 | this->Pressure.resize(numCells); 134 | std::fill(this->Pressure.begin(), this->Pressure.end(), 1.); 135 | } 136 | 137 | double* Attributes::GetVelocityArray() 138 | { 139 | if(this->Velocity.empty()) 140 | { 141 | return NULL; 142 | } 143 | return &this->Velocity[0]; 144 | } 145 | 146 | float* Attributes::GetPressureArray() 147 | { 148 | if(this->Pressure.empty()) 149 | { 150 | return NULL; 151 | } 152 | return &this->Pressure[0]; 153 | } 154 | -------------------------------------------------------------------------------- /CxxPVSMPipelineExample/FEDataStructures.h: -------------------------------------------------------------------------------- 1 | #ifndef FEDATASTRUCTURES_HEADER 2 | #define FEDATASTRUCTURES_HEADER 3 | 4 | #include 5 | #include 6 | 7 | class Grid 8 | { 9 | public: 10 | Grid(); 11 | void Initialize(const unsigned int numPoints[3], const double spacing[3]); 12 | size_t GetNumberOfPoints(); 13 | size_t GetNumberOfCells(); 14 | double* GetPointsArray(); 15 | double* GetPoint(size_t pointId); 16 | unsigned int* GetCellPoints(size_t cellId); 17 | private: 18 | std::vector Points; 19 | std::vector Cells; 20 | }; 21 | 22 | class Attributes 23 | { 24 | // A class for generating and storing point and cell fields. 25 | // Velocity is stored at the points and pressure is stored 26 | // for the cells. The current velocity profile is for a 27 | // shearing flow with U(y,t) = y*t, V = 0 and W = 0. 28 | // Pressure is constant through the domain. 29 | public: 30 | Attributes(); 31 | void Initialize(Grid* grid); 32 | void UpdateFields(double time); 33 | double* GetVelocityArray(); 34 | float* GetPressureArray(); 35 | 36 | private: 37 | std::vector Velocity; 38 | std::vector Pressure; 39 | Grid* GridPtr; 40 | }; 41 | #endif 42 | -------------------------------------------------------------------------------- /CxxPVSMPipelineExample/FEDriver.cxx: -------------------------------------------------------------------------------- 1 | #include "FEDataStructures.h" 2 | #include 3 | 4 | #ifdef USE_CATALYST 5 | #include 6 | #include "FEAdaptor.h" 7 | #include 8 | #endif 9 | 10 | // Example of a C++ adaptor for a simulation code 11 | // where we use a hard-coded ParaView server-manager 12 | // C++ pipeline. The simulation code has a fixed topology 13 | // grid. We treat the grid as an unstructured 14 | // grid even though in the example provided it 15 | // would be best described as a vtkImageData. 16 | // Also, the points are stored in an inconsistent 17 | // manner with respect to the velocity vector. 18 | // This is purposefully done to demonstrate 19 | // the different approaches for getting data 20 | // into Catalyst. The hard-coded C++ pipeline 21 | // uses a slice filter to cut 4 planes through 22 | // the domain. 23 | // Note that through configuration 24 | // that the driver can be run without linking 25 | // to Catalyst. 26 | 27 | int main(int argc, char* argv[]) 28 | { 29 | MPI_Init(&argc, &argv); 30 | Grid grid; 31 | unsigned int numPoints[3] = {70, 60, 44}; 32 | double spacing[3] = {1, 1.1, 1.3}; 33 | grid.Initialize(numPoints, spacing); 34 | Attributes attributes; 35 | attributes.Initialize(&grid); 36 | 37 | #ifdef USE_CATALYST 38 | bool doCoProcessing = false; 39 | if(argc == 3) 40 | { 41 | doCoProcessing = true; 42 | // pass in the number of time steps and base file name. 43 | FEAdaptor::Initialize(atoi(argv[1]), argv[2]); 44 | } 45 | else 46 | { 47 | std::cerr << "To run with Catalyst you must pass in the output frequency and the base file name.\n"; 48 | } 49 | #endif 50 | unsigned int numberOfTimeSteps = 15; 51 | for(unsigned int timeStep=0;timeStep 5 | #include 6 | 7 | class vtkCPDataDescription; 8 | class vtkCPPythonHelper; 9 | 10 | class vtkCPPVSMPipeline : public vtkCPPipeline 11 | { 12 | public: 13 | static vtkCPPVSMPipeline* New(); 14 | vtkTypeMacro(vtkCPPVSMPipeline,vtkCPPipeline); 15 | virtual void PrintSelf(ostream& os, vtkIndent indent); 16 | 17 | virtual void Initialize(int outputFrequency, std::string& fileName); 18 | 19 | virtual int RequestDataDescription(vtkCPDataDescription* dataDescription); 20 | 21 | virtual int CoProcess(vtkCPDataDescription* dataDescription); 22 | 23 | protected: 24 | vtkCPPVSMPipeline(); 25 | virtual ~vtkCPPVSMPipeline(); 26 | 27 | private: 28 | vtkCPPVSMPipeline(const vtkCPPVSMPipeline&); // Not implemented 29 | void operator=(const vtkCPPVSMPipeline&); // Not implemented 30 | 31 | int OutputFrequency; 32 | std::string FileName; 33 | }; 34 | #endif 35 | -------------------------------------------------------------------------------- /CxxVTKPipelineExample/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.8) 2 | project(CatalystCxxVTKPipelineExample) 3 | 4 | set(USE_CATALYST ON CACHE BOOL "Link the simulator with Catalyst") 5 | if(USE_CATALYST) 6 | # We have a C++ pipeline so we don't need to link with Python 7 | # or vtkPVPythonCatalyst since vtkPVCatalyst is sufficient. 8 | find_package(ParaView 4.1 REQUIRED COMPONENTS vtkPVCatalyst vtkPVVTKExtensionsDefault vtkPVClientServerCoreCore) 9 | include("${PARAVIEW_USE_FILE}") 10 | set(Adaptor_SRCS 11 | FEAdaptor.cxx 12 | vtkCPVTKPipeline.cxx 13 | ) 14 | add_library(CxxVTKPipelineExampleAdaptor ${Adaptor_SRCS}) 15 | target_link_libraries(CxxVTKPipelineExampleAdaptor vtkPVCatalyst vtkPVVTKExtensionsDefault vtkPVClientServerCoreCore) 16 | add_definitions("-DUSE_CATALYST") 17 | if(NOT PARAVIEW_USE_MPI) 18 | message(SEND_ERROR "ParaView must be built with MPI enabled") 19 | endif() 20 | else() 21 | find_package(MPI REQUIRED) 22 | include_directories(${MPI_CXX_INCLUDE_PATH}) 23 | endif() 24 | 25 | 26 | add_executable(CxxVTKPipelineExample FEDriver.cxx FEDataStructures.cxx) 27 | if(USE_CATALYST) 28 | target_link_libraries(CxxVTKPipelineExample LINK_PRIVATE CxxVTKPipelineExampleAdaptor) 29 | include(vtkModuleMacros) 30 | include(vtkMPI) 31 | vtk_mpi_link(CxxVTKPipelineExample) 32 | else() 33 | target_link_libraries(CxxVTKPipelineExample LINK_PRIVATE ${MPI_LIBRARIES}) 34 | endif() 35 | 36 | option(BUILD_TESTING "Build Testing" OFF) 37 | # Setup testing. 38 | if (BUILD_TESTING) 39 | include(CTest) 40 | add_test(CxxVTKPipelineExampleTest CxxVTKPipelineExample 10 output) 41 | endif() 42 | -------------------------------------------------------------------------------- /CxxVTKPipelineExample/FEAdaptor.h: -------------------------------------------------------------------------------- 1 | #ifndef FEADAPTOR_HEADER 2 | #define FEADAPTOR_HEADER 3 | 4 | #include 5 | 6 | class Attributes; 7 | class Grid; 8 | 9 | namespace FEAdaptor 10 | { 11 | void Initialize(int outputFrequency, std::string fileName); 12 | 13 | void Finalize(); 14 | 15 | void CoProcess(Grid& grid, Attributes& attributes, double time, 16 | unsigned int timeStep, bool lastTimeStep); 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /CxxVTKPipelineExample/FEDataStructures.cxx: -------------------------------------------------------------------------------- 1 | #include "FEDataStructures.h" 2 | 3 | #include 4 | #include 5 | 6 | Grid::Grid() 7 | {} 8 | 9 | void Grid::Initialize(const unsigned int numPoints[3], const double spacing[3] ) 10 | { 11 | if(numPoints[0] == 0 || numPoints[1] == 0 || numPoints[2] == 0) 12 | { 13 | std::cerr << "Must have a non-zero amount of points in each direction.\n"; 14 | } 15 | // in parallel, we do a simple partitioning in the x-direction. 16 | int mpiSize = 1; 17 | int mpiRank = 0; 18 | MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); 19 | MPI_Comm_size(MPI_COMM_WORLD, &mpiSize); 20 | 21 | unsigned int startXPoint = mpiRank*numPoints[0]/mpiSize; 22 | unsigned int endXPoint = (mpiRank+1)*numPoints[0]/mpiSize; 23 | if(mpiSize != mpiRank+1) 24 | { 25 | endXPoint++; 26 | } 27 | 28 | // create the points -- slowest in the x and fastest in the z directions 29 | double coord[3] = {0,0,0}; 30 | for(unsigned int i=startXPoint;iPoints)); 41 | } 42 | } 43 | } 44 | // create the hex cells 45 | unsigned int cellPoints[8]; 46 | unsigned int numXPoints = endXPoint - startXPoint; 47 | for(unsigned int i=0;iCells)); 70 | } 71 | } 72 | } 73 | } 74 | 75 | size_t Grid::GetNumberOfPoints() 76 | { 77 | return this->Points.size()/3; 78 | } 79 | 80 | size_t Grid::GetNumberOfCells() 81 | { 82 | return this->Cells.size()/8; 83 | } 84 | 85 | double* Grid::GetPointsArray() 86 | { 87 | if(this->Points.empty()) 88 | { 89 | return NULL; 90 | } 91 | return &(this->Points[0]); 92 | } 93 | 94 | double* Grid::GetPoint(size_t pointId) 95 | { 96 | if(pointId >= this->Points.size()) 97 | { 98 | return NULL; 99 | } 100 | return &(this->Points[pointId*3]); 101 | } 102 | 103 | unsigned int* Grid::GetCellPoints(size_t cellId) 104 | { 105 | if(cellId >= this->Cells.size()) 106 | { 107 | return NULL; 108 | } 109 | return &(this->Cells[cellId*8]); 110 | } 111 | 112 | Attributes::Attributes() 113 | { 114 | this->GridPtr = NULL; 115 | } 116 | 117 | void Attributes::Initialize(Grid* grid) 118 | { 119 | this->GridPtr = grid; 120 | } 121 | 122 | void Attributes::UpdateFields(double time) 123 | { 124 | size_t numPoints = this->GridPtr->GetNumberOfPoints(); 125 | this->Velocity.resize(numPoints*3); 126 | for(size_t pt=0;ptGridPtr->GetPoint(pt); 129 | this->Velocity[pt] = coord[1]*time; 130 | } 131 | std::fill(this->Velocity.begin()+numPoints, this->Velocity.end(), 0.); 132 | size_t numCells = this->GridPtr->GetNumberOfCells(); 133 | this->Pressure.resize(numCells); 134 | std::fill(this->Pressure.begin(), this->Pressure.end(), 1.); 135 | } 136 | 137 | double* Attributes::GetVelocityArray() 138 | { 139 | if(this->Velocity.empty()) 140 | { 141 | return NULL; 142 | } 143 | return &this->Velocity[0]; 144 | } 145 | 146 | float* Attributes::GetPressureArray() 147 | { 148 | if(this->Pressure.empty()) 149 | { 150 | return NULL; 151 | } 152 | return &this->Pressure[0]; 153 | } 154 | -------------------------------------------------------------------------------- /CxxVTKPipelineExample/FEDataStructures.h: -------------------------------------------------------------------------------- 1 | #ifndef FEDATASTRUCTURES_HEADER 2 | #define FEDATASTRUCTURES_HEADER 3 | 4 | #include 5 | #include 6 | 7 | class Grid 8 | { 9 | public: 10 | Grid(); 11 | void Initialize(const unsigned int numPoints[3], const double spacing[3]); 12 | size_t GetNumberOfPoints(); 13 | size_t GetNumberOfCells(); 14 | double* GetPointsArray(); 15 | double* GetPoint(size_t pointId); 16 | unsigned int* GetCellPoints(size_t cellId); 17 | private: 18 | std::vector Points; 19 | std::vector Cells; 20 | }; 21 | 22 | class Attributes 23 | { 24 | // A class for generating and storing point and cell fields. 25 | // Velocity is stored at the points and pressure is stored 26 | // for the cells. The current velocity profile is for a 27 | // shearing flow with U(y,t) = y*t, V = 0 and W = 0. 28 | // Pressure is constant through the domain. 29 | public: 30 | Attributes(); 31 | void Initialize(Grid* grid); 32 | void UpdateFields(double time); 33 | double* GetVelocityArray(); 34 | float* GetPressureArray(); 35 | 36 | private: 37 | std::vector Velocity; 38 | std::vector Pressure; 39 | Grid* GridPtr; 40 | }; 41 | #endif 42 | -------------------------------------------------------------------------------- /CxxVTKPipelineExample/FEDriver.cxx: -------------------------------------------------------------------------------- 1 | #include "FEDataStructures.h" 2 | #include 3 | 4 | #ifdef USE_CATALYST 5 | #include 6 | #include "FEAdaptor.h" 7 | #include 8 | #endif 9 | 10 | // Example of a C++ adaptor for a simulation code 11 | // where we use a hard-coded VTK C++ pipeline. 12 | // The simulation code has a fixed topology 13 | // grid. We treat the grid as an unstructured 14 | // grid even though in the example provided it 15 | // would be best described as a vtkImageData. 16 | // Also, the points are stored in an inconsistent 17 | // manner with respect to the velocity vector. 18 | // This is purposefully done to demonstrate 19 | // the different approaches for getting data 20 | // into Catalyst. The hard-coded C++ pipeline 21 | // computes the velocity magnitude from a velocity 22 | // vector and then uses a threshold filter to keep the 23 | // portion of the domain where velocity magnitude 24 | // is within the 10% of the maximum velocity. 25 | // Note that through configuration 26 | // that the driver can be run without linking 27 | // to Catalyst. 28 | 29 | int main(int argc, char* argv[]) 30 | { 31 | MPI_Init(&argc, &argv); 32 | Grid grid; 33 | unsigned int numPoints[3] = {70, 60, 44}; 34 | double spacing[3] = {1, 1.1, 1.3}; 35 | grid.Initialize(numPoints, spacing); 36 | Attributes attributes; 37 | attributes.Initialize(&grid); 38 | 39 | #ifdef USE_CATALYST 40 | bool doCoProcessing = false; 41 | if(argc == 3) 42 | { 43 | doCoProcessing = true; 44 | // pass in the number of time steps and base file name. 45 | FEAdaptor::Initialize(atoi(argv[1]), argv[2]); 46 | } 47 | else 48 | { 49 | std::cerr << "To run with Catalyst you must pass in the output frequency and the base file name.\n"; 50 | } 51 | #endif 52 | unsigned int numberOfTimeSteps = 100; 53 | for(unsigned int timeStep=0;timeStep 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | 22 | vtkStandardNewMacro(vtkCPVTKPipeline); 23 | 24 | //---------------------------------------------------------------------------- 25 | vtkCPVTKPipeline::vtkCPVTKPipeline() 26 | { 27 | this->OutputFrequency = 0; 28 | } 29 | 30 | //---------------------------------------------------------------------------- 31 | vtkCPVTKPipeline::~vtkCPVTKPipeline() 32 | { 33 | } 34 | 35 | //---------------------------------------------------------------------------- 36 | void vtkCPVTKPipeline::Initialize(int outputFrequency, std::string& fileName) 37 | { 38 | this->OutputFrequency = outputFrequency; 39 | this->FileName = fileName; 40 | } 41 | 42 | //---------------------------------------------------------------------------- 43 | int vtkCPVTKPipeline::RequestDataDescription( 44 | vtkCPDataDescription* dataDescription) 45 | { 46 | if(!dataDescription) 47 | { 48 | vtkWarningMacro("dataDescription is NULL."); 49 | return 0; 50 | } 51 | 52 | if(this->FileName.empty()) 53 | { 54 | vtkWarningMacro("No output file name given to output results to."); 55 | return 0; 56 | } 57 | 58 | if(dataDescription->GetForceOutput() == true || 59 | (this->OutputFrequency != 0 && dataDescription->GetTimeStep() % this->OutputFrequency == 0) ) 60 | { 61 | dataDescription->GetInputDescriptionByName("input")->AllFieldsOn(); 62 | dataDescription->GetInputDescriptionByName("input")->GenerateMeshOn(); 63 | return 1; 64 | } 65 | return 0; 66 | } 67 | 68 | //---------------------------------------------------------------------------- 69 | int vtkCPVTKPipeline::CoProcess( 70 | vtkCPDataDescription* dataDescription) 71 | { 72 | if(!dataDescription) 73 | { 74 | vtkWarningMacro("DataDescription is NULL"); 75 | return 0; 76 | } 77 | vtkUnstructuredGrid* grid = vtkUnstructuredGrid::SafeDownCast( 78 | dataDescription->GetInputDescriptionByName("input")->GetGrid()); 79 | if(grid == NULL) 80 | { 81 | vtkWarningMacro("DataDescription is missing input unstructured grid."); 82 | return 0; 83 | } 84 | if(this->RequestDataDescription(dataDescription) == 0) 85 | { 86 | return 1; 87 | } 88 | 89 | vtkNew producer; 90 | producer->SetOutput(grid); 91 | 92 | vtkNew calculator; 93 | calculator->SetInputConnection(producer->GetOutputPort()); 94 | calculator->SetAttributeMode(1); 95 | calculator->SetResultArrayName("velocity magnitude"); 96 | calculator->SetFunction("mag(velocity)"); 97 | 98 | // update now so that we can get the global data bounds of 99 | // the velocity magnitude for thresholding 100 | calculator->Update(); 101 | double range[2]; 102 | vtkUnstructuredGrid::SafeDownCast(calculator->GetOutput())->GetPointData() 103 | ->GetArray("velocity magnitude")->GetRange(range, 0); 104 | double globalRange[2]; 105 | vtkMultiProcessController::GetGlobalController()->AllReduce( 106 | range+1, globalRange+1, 1, vtkCommunicator::MAX_OP); 107 | 108 | vtkNew threshold; 109 | threshold->SetInputConnection(calculator->GetOutputPort()); 110 | threshold->SetInputArrayToProcess( 111 | 0, 0, 0, "vtkDataObject::FIELD_ASSOCIATION_POINTS", "velocity magnitude"); 112 | threshold->ThresholdBetween(0.9*globalRange[1], globalRange[1]); 113 | 114 | // If process 0 doesn't have any points or cells, the writer may 115 | // have problems in parallel so we use completeArrays to fill in 116 | // the missing information. 117 | vtkNew completeArrays; 118 | completeArrays->SetInputConnection(threshold->GetOutputPort()); 119 | 120 | vtkNew writer; 121 | writer->SetInputConnection(completeArrays->GetOutputPort()); 122 | std::ostringstream o; 123 | o << dataDescription->GetTimeStep(); 124 | std::string name = this->FileName + o.str() + ".pvtu"; 125 | writer->SetFileName(name.c_str()); 126 | writer->Update(); 127 | 128 | return 1; 129 | } 130 | 131 | //---------------------------------------------------------------------------- 132 | void vtkCPVTKPipeline::PrintSelf(ostream& os, vtkIndent indent) 133 | { 134 | this->Superclass::PrintSelf(os, indent); 135 | os << indent << "OutputFrequency: " << this->OutputFrequency << "\n"; 136 | os << indent << "FileName: " << this->FileName << "\n"; 137 | } 138 | -------------------------------------------------------------------------------- /CxxVTKPipelineExample/vtkCPVTKPipeline.h: -------------------------------------------------------------------------------- 1 | #ifndef VTKCPVTKPIPELINE_H 2 | #define VTKCPVTKPIPELINE_H 3 | 4 | #include 5 | #include 6 | 7 | class vtkCPDataDescription; 8 | class vtkCPPythonHelper; 9 | 10 | class vtkCPVTKPipeline : public vtkCPPipeline 11 | { 12 | public: 13 | static vtkCPVTKPipeline* New(); 14 | vtkTypeMacro(vtkCPVTKPipeline,vtkCPPipeline); 15 | virtual void PrintSelf(ostream& os, vtkIndent indent); 16 | 17 | virtual void Initialize(int outputFrequency, std::string& fileName); 18 | 19 | virtual int RequestDataDescription(vtkCPDataDescription* dataDescription); 20 | 21 | virtual int CoProcess(vtkCPDataDescription* dataDescription); 22 | 23 | protected: 24 | vtkCPVTKPipeline(); 25 | virtual ~vtkCPVTKPipeline(); 26 | 27 | private: 28 | vtkCPVTKPipeline(const vtkCPVTKPipeline&); // Not implemented 29 | void operator=(const vtkCPVTKPipeline&); // Not implemented 30 | 31 | int OutputFrequency; 32 | std::string FileName; 33 | }; 34 | #endif 35 | -------------------------------------------------------------------------------- /Fortran90FullExample/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(CatalystFortran90FullExample CXX Fortran) 3 | 4 | find_package(ParaView 4.1 REQUIRED COMPONENTS vtkPVPythonCatalyst) 5 | 6 | include(${PARAVIEW_USE_FILE}) 7 | if(NOT PARAVIEW_USE_MPI) 8 | message(SEND_ERROR "ParaView must be built with MPI enabled") 9 | endif() 10 | if(NOT MPI_Fortran_LIBRARIES) 11 | find_package(MPI) 12 | endif() 13 | 14 | add_executable(Fortran90FullExample FEDriver.f90 FEFortranAdaptor.f90 FECxxAdaptor.cxx) 15 | target_link_libraries(Fortran90FullExample vtkPVPythonCatalyst ${MPI_Fortran_LIBRARIES}) 16 | set_target_properties(Fortran90FullExample PROPERTIES 17 | LINKER_LANGUAGE Fortran) 18 | 19 | option(BUILD_TESTING "Build Testing" OFF) 20 | # Setup testing. 21 | if (BUILD_TESTING) 22 | file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/SampleScripts/coproc.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) 23 | include(CTest) 24 | add_test(Fortran90FullExampleTest Fortran90FullExample) 25 | endif() 26 | -------------------------------------------------------------------------------- /Fortran90FullExample/FECxxAdaptor.cxx: -------------------------------------------------------------------------------- 1 | // Adaptor for getting Fortran simulation code into ParaView CoProcessor. 2 | 3 | // CoProcessor specific headers 4 | #include "vtkCPDataDescription.h" 5 | #include "vtkCPInputDataDescription.h" 6 | #include "vtkCPProcessor.h" 7 | #include "vtkCPPythonScriptPipeline.h" 8 | #include "vtkSmartPointer.h" 9 | #include "vtkDoubleArray.h" 10 | #include "vtkPointData.h" 11 | #include "vtkImageData.h" 12 | 13 | // Fortran specific header 14 | #include "vtkCPPythonAdaptorAPI.h" 15 | 16 | 17 | // These will be called from the Fortran "glue" code" 18 | // Completely dependent on data layout, structured vs. unstructured, etc. 19 | // since VTK/ParaView uses different internal layouts for each. 20 | 21 | // Creates the data container for the CoProcessor. 22 | extern "C" void createcpimagedata_(int* nxstart, int* nxend, int* nx, 23 | int* ny, int* nz) 24 | { 25 | if (!vtkCPPythonAdaptorAPI::GetCoProcessorData()) 26 | { 27 | vtkGenericWarningMacro("Unable to access CoProcessorData."); 28 | return; 29 | } 30 | 31 | // The simulation grid is a 3-dimensional topologically and geometrically 32 | // regular grid. In VTK/ParaView, this is considered an image data set. 33 | vtkSmartPointer grid = vtkSmartPointer::New(); 34 | 35 | grid->SetExtent(*nxstart-1, *nxend-1, 0, *ny-1, 0, *nz-1); 36 | 37 | // Name should be consistent between here, Fortran and Python client script. 38 | vtkCPPythonAdaptorAPI::GetCoProcessorData()->GetInputDescriptionByName("input")->SetGrid(grid); 39 | vtkCPPythonAdaptorAPI::GetCoProcessorData()->GetInputDescriptionByName("input")->SetWholeExtent(0, *nx-1, 0, *ny-1, 0, *nz-1); 40 | } 41 | 42 | // Add field(s) to the data container. 43 | // Separate from above because this will be dynamic, grid is static. 44 | // By hand name mangling for fortran. 45 | extern "C" void addfield_(double* scalars, char* name) 46 | { 47 | vtkCPInputDataDescription* idd = 48 | vtkCPPythonAdaptorAPI::GetCoProcessorData()->GetInputDescriptionByName("input"); 49 | 50 | vtkImageData* Image = vtkImageData::SafeDownCast(idd->GetGrid()); 51 | 52 | if (!Image) 53 | { 54 | vtkGenericWarningMacro("No adaptor grid to attach field data to."); 55 | return; 56 | } 57 | 58 | // field name must match that in the fortran code. 59 | if (idd->IsFieldNeeded(name)) 60 | { 61 | vtkSmartPointer field = vtkSmartPointer::New(); 62 | field->SetNumberOfComponents(2); 63 | field->SetName(name); 64 | field->SetArray(scalars, 2*Image->GetNumberOfPoints(), 1); 65 | Image->GetPointData()->AddArray(field); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Fortran90FullExample/FEDriver.f90: -------------------------------------------------------------------------------- 1 | ! A Fortran Catalyst example. Note that coproc.py 2 | ! must be in the directory where the example 3 | ! is run from. 4 | ! Thanks to Lucas Pettey for helping create the example. 5 | 6 | PROGRAM coproc 7 | use tcp 8 | implicit none 9 | include 'mpif.h' 10 | integer,parameter :: nx=100,ny=100,nz=100,ntime=10 11 | integer :: i,j,k,time,nxstart,nxend 12 | real :: max 13 | complex(kind=8), allocatable :: psi01(:,:,:) 14 | integer :: numtasks,rank,ierr 15 | 16 | call mpi_init(ierr) 17 | call mpi_comm_size(MPI_COMM_WORLD, numtasks, ierr) 18 | call mpi_comm_rank(MPI_COMM_WORLD, rank, ierr) 19 | 20 | call coprocessorinitializewithpython("coproc.py",9) 21 | 22 | ! partition in the x-direction only 23 | nxstart=rank*nx/numtasks+1 24 | nxend=(rank+1)*nx/numtasks 25 | if(numtasks .ne. rank+1) then 26 | nxend=nxend+1 27 | endif 28 | 29 | allocate(psi01(nxend-nxstart+1,ny,nz)) 30 | ! set initial values 31 | max=sqrt(real(nx)**2+real(ny)**2+real(nz)**2) 32 | do k=1,nz 33 | do j=1,ny 34 | do i=1,nxend-nxstart+1 35 | psi01(i,j,k)=CMPLX(max-sqrt(real(i-50)**2+real(j-50)**2+real(k-50)**2),& 36 | real(1+j+k))/max*100.0 37 | enddo 38 | enddo 39 | enddo 40 | 41 | do time=1,ntime 42 | do k=1,nz 43 | do j=1,ny 44 | do i=1,nxend-nxstart+1 45 | psi01(i,j,k)=CMPLX(real(0.30),0.0)+psi01(i,j,k) 46 | end do 47 | end do 48 | end do 49 | call testcoprocessor(nxstart,nxend,nx,ny,nz,time,dble(time),psi01) 50 | enddo 51 | deallocate(psi01) 52 | 53 | call coprocessorfinalize() 54 | call mpi_finalize(ierr) 55 | 56 | end program coproc 57 | -------------------------------------------------------------------------------- /Fortran90FullExample/FEFortranAdaptor.f90: -------------------------------------------------------------------------------- 1 | module tcp 2 | use iso_c_binding 3 | implicit none 4 | public 5 | interface tcp_adaptor 6 | module procedure testcoprocessor 7 | end interface 8 | contains 9 | 10 | subroutine testcoprocessor(nxstart,nxend,nx,ny,nz,step,time,psi01) 11 | use iso_c_binding 12 | implicit none 13 | integer, intent(in) :: nxstart,nxend,nx,ny,nz,step 14 | real(kind=8), intent(in) :: time 15 | complex(kind=8), dimension(:,:,:), intent (in) :: psi01 16 | integer :: flag 17 | call requestdatadescription(step,time,flag) 18 | if (flag .ne. 0) then 19 | call needtocreategrid(flag) 20 | if (flag .ne. 0) then 21 | call createcpimagedata(nxstart,nxend,nx,nz,nz) 22 | end if 23 | ! adding //char(0) appends the C++ terminating character 24 | ! to the Fortran array 25 | call addfield(psi01,"psi01"//char(0)) 26 | call coprocess() 27 | end if 28 | 29 | return 30 | 31 | end subroutine 32 | end module tcp 33 | 34 | -------------------------------------------------------------------------------- /Fortran90FullExample/SampleScripts/coproc.py: -------------------------------------------------------------------------------- 1 | 2 | try: paraview.simple 3 | except: from paraview.simple import * 4 | 5 | from paraview import coprocessing 6 | 7 | 8 | #-------------------------------------------------------------- 9 | # Code generated from cpstate.py to create the CoProcessor. 10 | 11 | 12 | # ----------------------- CoProcessor definition ----------------------- 13 | 14 | def CreateCoProcessor(): 15 | def _CreatePipeline(coprocessor, datadescription): 16 | class Pipeline: 17 | filename_6_pvti = coprocessor.CreateProducer( datadescription, "input" ) 18 | 19 | Slice1 = Slice( guiName="Slice1", Crinkleslice=0, SliceOffsetValues=[0.0], Triangulatetheslice=1, SliceType="Plane" ) 20 | Slice1.SliceType.Offset = 0.0 21 | Slice1.SliceType.Origin = [49.5, 49.5, 49.5] 22 | Slice1.SliceType.Normal = [1.0, 0.0, 0.0] 23 | 24 | ParallelPolyDataWriter1 = coprocessor.CreateWriter( XMLPPolyDataWriter, "slice_%t.pvtp", 10 ) 25 | 26 | return Pipeline() 27 | 28 | class CoProcessor(coprocessing.CoProcessor): 29 | def CreatePipeline(self, datadescription): 30 | self.Pipeline = _CreatePipeline(self, datadescription) 31 | 32 | coprocessor = CoProcessor() 33 | freqs = {'input': [10]} 34 | coprocessor.SetUpdateFrequencies(freqs) 35 | return coprocessor 36 | 37 | #-------------------------------------------------------------- 38 | # Global variables that will hold the pipeline for each timestep 39 | # Creating the CoProcessor object, doesn't actually create the ParaView pipeline. 40 | # It will be automatically setup when coprocessor.UpdateProducers() is called the 41 | # first time. 42 | coprocessor = CreateCoProcessor() 43 | 44 | #-------------------------------------------------------------- 45 | # Enable Live-Visualizaton with ParaView 46 | coprocessor.EnableLiveVisualization(False) 47 | 48 | 49 | # ---------------------- Data Selection method ---------------------- 50 | 51 | def RequestDataDescription(datadescription): 52 | "Callback to populate the request for current timestep" 53 | global coprocessor 54 | if datadescription.GetForceOutput() == True: 55 | # We are just going to request all fields and meshes from the simulation 56 | # code/adaptor. 57 | for i in range(datadescription.GetNumberOfInputDescriptions()): 58 | datadescription.GetInputDescription(i).AllFieldsOn() 59 | datadescription.GetInputDescription(i).GenerateMeshOn() 60 | return 61 | 62 | # setup requests for all inputs based on the requirements of the 63 | # pipeline. 64 | coprocessor.LoadRequestedData(datadescription) 65 | 66 | # ------------------------ Processing method ------------------------ 67 | 68 | def DoCoProcessing(datadescription): 69 | "Callback to do co-processing for current timestep" 70 | global coprocessor 71 | 72 | # Update the coprocessor by providing it the newly generated simulation data. 73 | # If the pipeline hasn't been setup yet, this will setup the pipeline. 74 | coprocessor.UpdateProducers(datadescription) 75 | 76 | # Write output data, if appropriate. 77 | coprocessor.WriteData(datadescription); 78 | 79 | # Write image capture (Last arg: rescale lookup table), if appropriate. 80 | coprocessor.WriteImages(datadescription, rescale_lookuptable=False) 81 | 82 | # Live Visualization, if enabled. 83 | coprocessor.DoLiveVisualization(datadescription, "localhost", 22222) 84 | -------------------------------------------------------------------------------- /FortranPoissonSolver/Box.F90: -------------------------------------------------------------------------------- 1 | module Box 2 | implicit none 3 | public :: getownedbox, getlocalbox 4 | 5 | contains 6 | 7 | ! this gives a partitioning of an extent based on its inputs. 8 | ! the partitioning will overlap (e.g. 0 to 10 partitioned into 9 | ! 2 pieces would result in 0-5 and 5-10). arguments are: 10 | ! piece: which piece to get the partition for (between 1 and numpieces) 11 | ! numpieces: the number of pieces that the extent is partitioned into 12 | ! globalbox: the extent where the values are ordered by 13 | ! {max x index, max y index, max z index} 14 | ! box: the returned local extent where the values are ordered by 15 | ! {min x index, max x index, min y index, max y index, min z index, max z index} 16 | subroutine getlocalbox(piece, numpieces, dimensions, box) 17 | implicit none 18 | integer, intent(in) :: piece, numpieces, dimensions(3) 19 | integer, intent(inout) :: box(6) 20 | integer :: numpiecesinfirsthalf, splitaxis, mid, cnt 21 | integer :: numpieceslocal, piecelocal, i, size(3) 22 | 23 | do i=1, 3 24 | box((i-1)*2+1) = 1 25 | box(2*i) = dimensions(i) 26 | enddo 27 | 28 | if (piece .gt. numpieces .or. piece .lt. 0) return 29 | ! keep splitting until we have only one piece. 30 | ! piece and numpieces will always be relative to the current box. 31 | cnt = 0 32 | numpieceslocal = numpieces 33 | piecelocal = piece-1 34 | do while (numpieceslocal .gt. 1) 35 | size(1) = box(2) - box(1) 36 | size(2) = box(4) - box(3) 37 | size(3) = box(6) - box(5) 38 | ! choose what axis to split on based on the SplitMode 39 | ! if the user has requested x, y, or z slabs then try to 40 | ! honor that request. If that axis is already split as 41 | ! far as it can go, then drop to block mode. 42 | ! choose the biggest axis 43 | if (size(3) .ge. size(2) .and. size(3) .ge. size(1) .and. size(3)/2 .ge. 1) then 44 | splitaxis = 3 45 | else if (size(2) .ge. size(1) .and. size(2)/2 .ge. 1) then 46 | splitaxis = 2 47 | else if (size(1)/2 .ge. 1) then 48 | splitaxis = 1 49 | else 50 | splitaxis = -1 51 | endif 52 | 53 | if (splitaxis .eq. -1) then 54 | ! can not split any more. 55 | if (piecelocal .eq. 0) then 56 | ! just return the remaining piece 57 | numpieceslocal = 1 58 | else 59 | ! the rest must be empty 60 | return 61 | endif 62 | else ! (splitaxis .eq. -1) 63 | ! split the chosen axis into two pieces. 64 | numpiecesinfirsthalf = (numpieceslocal / 2) 65 | mid = size(splitaxis) 66 | mid = (mid * numpiecesinfirsthalf) / numpieceslocal + box((splitaxis-1)*2+1) 67 | if (piecelocal .lt. numpiecesinfirsthalf) then 68 | ! piece is in the first half 69 | ! set boxent to the first half of the previous value. 70 | box((splitaxis-1)*2+2) = mid 71 | ! piece must adjust. 72 | numpieceslocal = numpiecesinfirsthalf 73 | else 74 | ! piece is in the second half. 75 | ! set the boxent to be the second half. (two halves share points) 76 | box((splitaxis-1)*2+1) = mid 77 | ! piece must adjust 78 | numpieceslocal = numpieceslocal - numpiecesinfirsthalf 79 | piecelocal = piecelocal - numpiecesinfirsthalf 80 | endif 81 | endif 82 | end do 83 | return 84 | end subroutine getlocalbox 85 | 86 | ! box is only locally owned on the minimum side of that 87 | ! is at the domain boundary 88 | subroutine getownedbox(piece, numpieces, dimensions, ownedbox) 89 | implicit none 90 | integer, intent(in) :: dimensions(3), piece, numpieces 91 | integer, intent(out) :: ownedbox(6) 92 | integer :: i, localbox(6) 93 | 94 | call getlocalbox(piece, numpieces, dimensions, localbox) 95 | 96 | do i=1, 3 97 | ! minimums 98 | if(localbox((i-1)*2+1) .eq. 1) then 99 | ownedbox((i-1)*2+1) = 1 100 | else 101 | if(localbox((i-1)*2+1) .ne. dimensions(i)) then 102 | ownedbox((i-1)*2+1) = localbox((i-1)*2+1)+1 103 | else 104 | ! this happens when the domain has a single point in this direction 105 | ownedbox((i-1)*2+1) = 1 106 | endif 107 | endif 108 | ! maximums 109 | ownedbox(i*2) = localbox(i*2) 110 | end do 111 | 112 | end subroutine getownedbox 113 | 114 | end module Box 115 | -------------------------------------------------------------------------------- /FortranPoissonSolver/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(CatalystFortranPoissonSolver CXX Fortran) 3 | 4 | set(SOURCES 5 | FEDriver.F90 6 | Box.F90 7 | SparseMatrix.F90 8 | ConjugateGradient.F90 9 | PoissonDiscretization.F90 10 | ) 11 | 12 | set(USE_CATALYST ON CACHE BOOL "Link the simulator with Catalyst") 13 | if(USE_CATALYST) 14 | find_package(ParaView 4.1 REQUIRED COMPONENTS vtkPVPythonCatalyst) 15 | include("${PARAVIEW_USE_FILE}") 16 | # we don't create a separate library for the adaptor here 17 | # since FEFortranAdaptor.F90 depends on Box.F90 18 | list(APPEND SOURCES FEFortranAdaptor.F90 FECxxAdaptor.cxx) 19 | add_definitions("-DUSE_CATALYST") 20 | if(NOT PARAVIEW_USE_MPI) 21 | message(SEND_ERROR "ParaView must be built with MPI enabled") 22 | endif() 23 | else() 24 | find_package(MPI REQUIRED) 25 | include_directories(${MPI_Fortran_INCLUDE_PATH}) 26 | endif() 27 | 28 | add_executable(FortranPoissonSolver ${SOURCES}) 29 | target_link_libraries(FortranPoissonSolver ${MPI_Fortran_LIBRARIES}) 30 | if(USE_CATALYST) 31 | target_link_libraries(FortranPoissonSolver vtkPVPythonCatalyst vtkParallelMPI) 32 | endif() 33 | set_target_properties(FortranPoissonSolver PROPERTIES 34 | LINKER_LANGUAGE Fortran) 35 | 36 | option(BUILD_TESTING "Build Testing" OFF) 37 | # Setup testing. 38 | if (BUILD_TESTING) 39 | file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/SampleScripts/coproc.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) 40 | include(CTest) 41 | add_test(FortranPoissonSolverTest FortranPoissonSolver coproc.py) 42 | endif() 43 | -------------------------------------------------------------------------------- /FortranPoissonSolver/ConjugateGradient.F90: -------------------------------------------------------------------------------- 1 | module ConjugateGradient 2 | use SparseMatrix 3 | #ifdef USE_CATALYST 4 | use CoProcessor 5 | #endif 6 | implicit none 7 | private :: dotproduct 8 | public :: solve 9 | 10 | contains 11 | 12 | real(kind=8) function dotproduct(sm, a, b) 13 | type(SparseMatrixData), intent(inout) :: sm 14 | integer :: i 15 | real(kind=8), intent(in) :: a(:), b(:) 16 | real(kind=8) :: value 17 | 18 | value = 0.d0 19 | do i=1, sm%globalsize 20 | value = value + a(i)*b(i) 21 | enddo 22 | dotproduct = value 23 | end function dotproduct 24 | 25 | subroutine solve(dimensions, sm, x, rhs) 26 | type(SparseMatrixData), intent(inout) :: sm 27 | integer, intent(in) :: dimensions(3) 28 | real(kind=8), intent(in) :: rhs(:) 29 | real(kind=8), intent(inout) :: x(:) 30 | integer :: k, i 31 | real(kind=8) :: alpha, beta, rdotproduct, rnewdotproduct, sqrtorigresid 32 | real(kind=8), DIMENSION(:), allocatable :: r(:), p(:), ap(:) 33 | 34 | allocate(r(sm%globalsize), p(sm%globalsize), ap(sm%globalsize)) 35 | 36 | #ifdef USE_CATALYST 37 | x(:) = 0.d0 38 | call runcoprocessor(dimensions, 0, 0.d0, x) 39 | #endif 40 | 41 | r(:) = rhs(:) 42 | p(:) = rhs(:) 43 | k = 1 44 | rdotproduct = dotproduct(sm, r, r) 45 | sqrtorigresid = sqrt(rdotproduct) 46 | do while(k .le. sm%globalsize .and. sqrt(rdotproduct) .gt. sqrtorigresid*0.000001d0) 47 | call matvec(sm, p, ap) 48 | alpha = rdotproduct/dotproduct(sm, ap, p) 49 | x(:) = x(:) + alpha*p(:) 50 | r(:) = r(:) - alpha*ap(:) 51 | rnewdotproduct = dotproduct(sm, r, r) 52 | beta = rnewdotproduct/rdotproduct 53 | p(:) = r(:) + beta*p(:) 54 | rdotproduct = rnewdotproduct 55 | !write(*,*) 'on iteration ', k, sqrtorigresid, sqrt(rdotproduct), alpha 56 | #ifdef USE_CATALYST 57 | call runcoprocessor(dimensions, k, k*1.d0, x) 58 | #endif 59 | k = k+1 60 | end do 61 | 62 | deallocate(r, p, ap) 63 | 64 | end subroutine solve 65 | 66 | 67 | end module ConjugateGradient 68 | -------------------------------------------------------------------------------- /FortranPoissonSolver/FECxxAdaptor.cxx: -------------------------------------------------------------------------------- 1 | // Adaptor for getting Fortran simulation code into ParaView Catalyst. 2 | 3 | // CoProcessor specific headers 4 | #include "vtkCPDataDescription.h" 5 | #include "vtkCPInputDataDescription.h" 6 | #include "vtkCPProcessor.h" 7 | #include "vtkSmartPointer.h" 8 | #include "vtkDoubleArray.h" 9 | #include "vtkPointData.h" 10 | #include "vtkImageData.h" 11 | 12 | // Fortran specific header 13 | #include "vtkCPPythonAdaptorAPI.h" 14 | 15 | // These will be called from the Fortran "glue" code" 16 | // Completely dependent on data layout, structured vs. unstructured, etc. 17 | // since VTK/ParaView uses different internal layouts for each. 18 | 19 | // Creates the data container for the CoProcessor. 20 | extern "C" void createcpimagedata_(int* dimensions, int* extent) 21 | { 22 | if (!vtkCPPythonAdaptorAPI::GetCoProcessorData()) 23 | { 24 | vtkGenericWarningMacro("Unable to access CoProcessorData."); 25 | return; 26 | } 27 | 28 | // The simulation grid is a 3-dimensional topologically and geometrically 29 | // regular grid. In VTK/ParaView, this is considered an image data set. 30 | vtkSmartPointer grid = vtkSmartPointer::New(); 31 | 32 | grid->SetExtent(extent[0]-1, extent[1]-1, extent[2]-1, 33 | extent[3]-1, extent[4]-1, extent[5]-1); 34 | grid->SetSpacing(1./(dimensions[0]-1), 1./(dimensions[1]-1), 1./(dimensions[2]-1)); 35 | 36 | // Name should be consistent between here, Fortran and Python client script. 37 | vtkCPPythonAdaptorAPI::GetCoProcessorData()->GetInputDescriptionByName("input")->SetGrid(grid); 38 | vtkCPPythonAdaptorAPI::GetCoProcessorData()->GetInputDescriptionByName("input")->SetWholeExtent( 39 | 0, dimensions[0]-1, 0, dimensions[1]-1, 0, dimensions[2]-1); 40 | } 41 | 42 | // Add field(s) to the data container. 43 | // Separate from above because this will be dynamic, grid is static. 44 | // By hand name mangling for fortran. 45 | extern "C" void addfield_(double* scalars, char* name) 46 | { 47 | vtkCPInputDataDescription* idd = 48 | vtkCPPythonAdaptorAPI::GetCoProcessorData()->GetInputDescriptionByName("input"); 49 | 50 | vtkImageData* image = vtkImageData::SafeDownCast(idd->GetGrid()); 51 | 52 | if (!image) 53 | { 54 | vtkGenericWarningMacro("No adaptor grid to attach field data to."); 55 | return; 56 | } 57 | 58 | // field name must match that in the fortran code. 59 | if (idd->IsFieldNeeded(name)) 60 | { 61 | vtkSmartPointer field = vtkSmartPointer::New(); 62 | field->SetName(name); 63 | field->SetArray(scalars, image->GetNumberOfPoints(), 1); 64 | image->GetPointData()->AddArray(field); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /FortranPoissonSolver/FEDriver.F90: -------------------------------------------------------------------------------- 1 | PROGRAM coproc 2 | #ifdef USE_CATALYST 3 | use CoProcessor ! ParaView Catalyst adaptor 4 | #endif 5 | use SparseMatrix ! contains initialize() and finalize() 6 | use PoissonDiscretization ! contains fillmatrixandrhs() 7 | use ConjugateGradient ! contains solve() 8 | use Box ! contains getownedbox() 9 | implicit none 10 | include 'mpif.h' 11 | integer :: numtasks,rank,ierr,allocatestatus 12 | integer :: dimensions(3), ownedbox(6) 13 | type(SparseMatrixData) :: sm 14 | real(kind=8), DIMENSION(:), allocatable :: x, rhs 15 | 16 | call mpi_init(ierr) 17 | call mpi_comm_size(MPI_COMM_WORLD, numtasks, ierr) 18 | call mpi_comm_rank(MPI_COMM_WORLD, rank, ierr) 19 | 20 | #ifdef USE_CATALYST 21 | call initializecoprocessor() 22 | #endif 23 | 24 | dimensions(1) = 10 25 | dimensions(2) = 10 26 | dimensions(3) = 10 27 | 28 | ! given a piece between 1 and numtasks, compute the nodes that 29 | ! are owned by this process (ownedbox) 30 | call getownedbox(rank+1, numtasks, dimensions, ownedbox) 31 | 32 | call initialize(sm, ownedbox, dimensions) 33 | 34 | ! each process has a full copy of the solution and the RHS to keep things simple 35 | allocate(x(dimensions(1)*dimensions(2)*dimensions(3)), rhs(dimensions(1)*dimensions(2)*dimensions(3)), STAT = allocatestatus) 36 | if (allocatestatus /= 0) STOP "*** FEDriver.F90: Not enough memory for arrays ***" 37 | 38 | call fillmatrixandrhs(sm, rhs, ownedbox, dimensions) 39 | 40 | call solve(dimensions, sm, x, rhs) 41 | 42 | #ifdef USE_CATALYST 43 | call finalizecoprocessor() 44 | #endif 45 | 46 | deallocate(x, rhs) 47 | 48 | call finalize(sm) 49 | 50 | call mpi_finalize(ierr) 51 | 52 | write(*,*) 'Finished on rank', rank, 'of', numtasks 53 | 54 | end program coproc 55 | -------------------------------------------------------------------------------- /FortranPoissonSolver/FEFortranAdaptor.F90: -------------------------------------------------------------------------------- 1 | module CoProcessor 2 | implicit none 3 | public initializecoprocessor, runcoprocessor, finalizecoprocessor 4 | 5 | contains 6 | 7 | subroutine initializecoprocessor() 8 | implicit none 9 | integer :: ilen, i 10 | character(len=200) :: arg 11 | 12 | call coprocessorinitialize() 13 | do i=1, iargc() 14 | call getarg(i, arg) 15 | ilen = len_trim(arg) 16 | arg(ilen+1:) = char(0) 17 | call coprocessoraddpythonscript(arg, ilen) 18 | enddo 19 | end subroutine initializecoprocessor 20 | 21 | subroutine runcoprocessor(dimensions, step, time, x) 22 | use iso_c_binding 23 | implicit none 24 | integer, intent(in) :: dimensions(3), step 25 | real(kind=8), dimension(:), intent(in) :: x 26 | real(kind=8), intent(in) :: time 27 | integer :: flag, extent(6) 28 | real(kind=8), DIMENSION(:), allocatable :: xcp(:) 29 | 30 | call requestdatadescription(step,time,flag) 31 | if (flag .ne. 0) then 32 | call needtocreategrid(flag) 33 | call getvtkextent(dimensions, extent) 34 | 35 | if (flag .ne. 0) then 36 | call createcpimagedata(dimensions, extent) 37 | end if 38 | ! x is the array with global values, we need just this process's 39 | ! values for Catalyst which will be put in xcp 40 | allocate(xcp((extent(2)-extent(1)+1)*(extent(4)-extent(3)+1)*(extent(6)-extent(5)+1))) 41 | call getlocalfield(dimensions, extent, x, xcp) 42 | 43 | ! adding //char(0) appends the C++ terminating character 44 | ! to the Fortran array 45 | call addfield(xcp,"solution"//char(0)) 46 | call coprocess() 47 | deallocate(xcp) 48 | end if 49 | end subroutine runcoprocessor 50 | 51 | subroutine finalizecoprocessor() 52 | call coprocessorfinalize() 53 | end subroutine finalizecoprocessor 54 | 55 | ! helper methods 56 | subroutine getvtkextent(dimensions, extent) 57 | use Box 58 | implicit none 59 | include 'mpif.h' 60 | integer, intent(in) :: dimensions(3) 61 | integer, intent(out) :: extent(6) 62 | integer :: numtasks, rank, ierr 63 | 64 | call mpi_comm_size(MPI_COMM_WORLD, numtasks, ierr) 65 | call mpi_comm_rank(MPI_COMM_WORLD, rank, ierr) 66 | call getlocalbox(rank+1, numtasks, dimensions, extent) 67 | end subroutine getvtkextent 68 | 69 | subroutine getlocalfield(dimensions, extent, x, xcp) 70 | implicit none 71 | integer :: i, j, k, counter 72 | integer, intent(in) :: dimensions(3), extent(6) 73 | real(kind=8), dimension(:), intent(in) :: x 74 | real(kind=8), dimension(:), intent(out) :: xcp 75 | counter = 1 76 | do k=extent(5), extent(6) 77 | do j=extent(3), extent(4) 78 | do i=extent(1), extent(2) 79 | xcp(counter) = x(i+(j-1)*dimensions(1)+(k-1)*dimensions(1)*dimensions(2)) 80 | counter = counter + 1 81 | enddo 82 | enddo 83 | enddo 84 | end subroutine getlocalfield 85 | 86 | end module CoProcessor 87 | -------------------------------------------------------------------------------- /FortranPoissonSolver/SampleScripts/coproc.py: -------------------------------------------------------------------------------- 1 | 2 | try: paraview.simple 3 | except: from paraview.simple import * 4 | 5 | from paraview import coprocessing 6 | 7 | 8 | #-------------------------------------------------------------- 9 | # Code generated from cpstate.py to create the CoProcessor. 10 | 11 | 12 | # ----------------------- CoProcessor definition ----------------------- 13 | 14 | def CreateCoProcessor(): 15 | def _CreatePipeline(coprocessor, datadescription): 16 | class Pipeline: 17 | filename_6_pvti = coprocessor.CreateProducer( datadescription, "input" ) 18 | 19 | Slice1 = Slice( guiName="Slice1", Crinkleslice=0, SliceOffsetValues=[0.0], Triangulatetheslice=1, SliceType="Plane" ) 20 | Slice1.SliceType.Offset = 0.0 21 | Slice1.SliceType.Origin = [49.5, 49.5, 49.5] 22 | Slice1.SliceType.Normal = [1.0, 0.0, 0.0] 23 | 24 | ParallelPolyDataWriter1 = coprocessor.CreateWriter( XMLPPolyDataWriter, "slice_%t.pvtp", 10 ) 25 | 26 | return Pipeline() 27 | 28 | class CoProcessor(coprocessing.CoProcessor): 29 | def CreatePipeline(self, datadescription): 30 | self.Pipeline = _CreatePipeline(self, datadescription) 31 | 32 | coprocessor = CoProcessor() 33 | freqs = {'input': [10]} 34 | coprocessor.SetUpdateFrequencies(freqs) 35 | return coprocessor 36 | 37 | #-------------------------------------------------------------- 38 | # Global variables that will hold the pipeline for each timestep 39 | # Creating the CoProcessor object, doesn't actually create the ParaView pipeline. 40 | # It will be automatically setup when coprocessor.UpdateProducers() is called the 41 | # first time. 42 | coprocessor = CreateCoProcessor() 43 | 44 | #-------------------------------------------------------------- 45 | # Enable Live-Visualizaton with ParaView 46 | coprocessor.EnableLiveVisualization(False) 47 | 48 | 49 | # ---------------------- Data Selection method ---------------------- 50 | 51 | def RequestDataDescription(datadescription): 52 | "Callback to populate the request for current timestep" 53 | global coprocessor 54 | if datadescription.GetForceOutput() == True: 55 | # We are just going to request all fields and meshes from the simulation 56 | # code/adaptor. 57 | for i in range(datadescription.GetNumberOfInputDescriptions()): 58 | datadescription.GetInputDescription(i).AllFieldsOn() 59 | datadescription.GetInputDescription(i).GenerateMeshOn() 60 | return 61 | 62 | # setup requests for all inputs based on the requirements of the 63 | # pipeline. 64 | coprocessor.LoadRequestedData(datadescription) 65 | 66 | # ------------------------ Processing method ------------------------ 67 | 68 | def DoCoProcessing(datadescription): 69 | "Callback to do co-processing for current timestep" 70 | global coprocessor 71 | 72 | # Update the coprocessor by providing it the newly generated simulation data. 73 | # If the pipeline hasn't been setup yet, this will setup the pipeline. 74 | coprocessor.UpdateProducers(datadescription) 75 | 76 | # Write output data, if appropriate. 77 | coprocessor.WriteData(datadescription); 78 | 79 | # Write image capture (Last arg: rescale lookup table), if appropriate. 80 | coprocessor.WriteImages(datadescription, rescale_lookuptable=False) 81 | 82 | # Live Visualization, if enabled. 83 | coprocessor.DoLiveVisualization(datadescription, "localhost", 22222) 84 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Kitware Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | Neither the name of Kitware Inc. nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /MPISubCommunicatorExample/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.8) 2 | project(CatalystMPISubCommunicatorExample) 3 | 4 | find_package(ParaView 4.2 REQUIRED COMPONENTS vtkPVPythonCatalyst) 5 | include("${PARAVIEW_USE_FILE}") 6 | if(NOT PARAVIEW_USE_MPI) 7 | message(SEND_ERROR "ParaView must be built with MPI enabled") 8 | endif() 9 | 10 | add_executable(MPISubCommunicatorExample FEDriver.cxx FEDataStructures.cxx FEAdaptor.cxx) 11 | target_link_libraries(MPISubCommunicatorExample LINK_PRIVATE vtkPVPythonCatalyst vtkParallelMPI) 12 | include(vtkModuleMacros) 13 | include(vtkMPI) 14 | vtk_mpi_link(MPISubCommunicatorExample) 15 | 16 | option(BUILD_TESTING "Build Testing" OFF) 17 | # Setup testing. 18 | if (BUILD_TESTING) 19 | include(CTest) 20 | add_test(MPISubCommunicatorExampleTest MPISubCommunicatorExample 21 | ${CMAKE_CURRENT_SOURCE_DIR}/SampleScripts/feslicescript.py) 22 | endif() 23 | -------------------------------------------------------------------------------- /MPISubCommunicatorExample/FEAdaptor.h: -------------------------------------------------------------------------------- 1 | #ifndef FEADAPTOR_HEADER 2 | #define FEADAPTOR_HEADER 3 | 4 | #include 5 | 6 | class Attributes; 7 | class Grid; 8 | 9 | namespace FEAdaptor 10 | { 11 | void Initialize(int numScripts, char* scripts[], MPI_Comm* comm); 12 | 13 | void Finalize(); 14 | 15 | void CoProcess(Grid& grid, Attributes& attributes, double time, 16 | unsigned int timeStep, bool lastTimeStep); 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /MPISubCommunicatorExample/FEDataStructures.cxx: -------------------------------------------------------------------------------- 1 | #include "FEDataStructures.h" 2 | 3 | #include 4 | #include 5 | 6 | Grid::Grid() 7 | {} 8 | 9 | void Grid::Initialize(const unsigned int numPoints[3], const double spacing[3] ) 10 | { 11 | if(numPoints[0] == 0 || numPoints[1] == 0 || numPoints[2] == 0) 12 | { 13 | std::cerr << "Must have a non-zero amount of points in each direction.\n"; 14 | } 15 | // in parallel, we do a simple partitioning in the x-direction. 16 | int mpiSize = 1; 17 | int mpiRank = 0; 18 | MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); 19 | MPI_Comm_size(MPI_COMM_WORLD, &mpiSize); 20 | 21 | unsigned int startXPoint = mpiRank*numPoints[0]/mpiSize; 22 | unsigned int endXPoint = (mpiRank+1)*numPoints[0]/mpiSize; 23 | if(mpiSize != mpiRank+1) 24 | { 25 | endXPoint++; 26 | } 27 | 28 | // create the points -- slowest in the x and fastest in the z directions 29 | double coord[3] = {0,0,0}; 30 | for(unsigned int i=startXPoint;iPoints)); 41 | } 42 | } 43 | } 44 | // create the hex cells 45 | unsigned int cellPoints[8]; 46 | unsigned int numXPoints = endXPoint - startXPoint; 47 | for(unsigned int i=0;iCells)); 70 | } 71 | } 72 | } 73 | } 74 | 75 | size_t Grid::GetNumberOfPoints() 76 | { 77 | return this->Points.size()/3; 78 | } 79 | 80 | size_t Grid::GetNumberOfCells() 81 | { 82 | return this->Cells.size()/8; 83 | } 84 | 85 | double* Grid::GetPointsArray() 86 | { 87 | if(this->Points.empty()) 88 | { 89 | return NULL; 90 | } 91 | return &(this->Points[0]); 92 | } 93 | 94 | double* Grid::GetPoint(size_t pointId) 95 | { 96 | if(pointId >= this->Points.size()) 97 | { 98 | return NULL; 99 | } 100 | return &(this->Points[pointId*3]); 101 | } 102 | 103 | unsigned int* Grid::GetCellPoints(size_t cellId) 104 | { 105 | if(cellId >= this->Cells.size()) 106 | { 107 | return NULL; 108 | } 109 | return &(this->Cells[cellId*8]); 110 | } 111 | 112 | Attributes::Attributes() 113 | { 114 | this->GridPtr = NULL; 115 | } 116 | 117 | void Attributes::Initialize(Grid* grid) 118 | { 119 | this->GridPtr = grid; 120 | } 121 | 122 | void Attributes::UpdateFields(double time) 123 | { 124 | size_t numPoints = this->GridPtr->GetNumberOfPoints(); 125 | this->Velocity.resize(numPoints*3); 126 | for(size_t pt=0;ptGridPtr->GetPoint(pt); 129 | this->Velocity[pt] = coord[1]*time; 130 | } 131 | std::fill(this->Velocity.begin()+numPoints, this->Velocity.end(), 0.); 132 | size_t numCells = this->GridPtr->GetNumberOfCells(); 133 | this->Pressure.resize(numCells); 134 | std::fill(this->Pressure.begin(), this->Pressure.end(), 1.); 135 | } 136 | 137 | double* Attributes::GetVelocityArray() 138 | { 139 | if(this->Velocity.empty()) 140 | { 141 | return NULL; 142 | } 143 | return &this->Velocity[0]; 144 | } 145 | 146 | float* Attributes::GetPressureArray() 147 | { 148 | if(this->Pressure.empty()) 149 | { 150 | return NULL; 151 | } 152 | return &this->Pressure[0]; 153 | } 154 | -------------------------------------------------------------------------------- /MPISubCommunicatorExample/FEDataStructures.h: -------------------------------------------------------------------------------- 1 | #ifndef FEDATASTRUCTURES_HEADER 2 | #define FEDATASTRUCTURES_HEADER 3 | 4 | #include 5 | #include 6 | 7 | class Grid 8 | { 9 | public: 10 | Grid(); 11 | void Initialize(const unsigned int numPoints[3], const double spacing[3]); 12 | size_t GetNumberOfPoints(); 13 | size_t GetNumberOfCells(); 14 | double* GetPointsArray(); 15 | double* GetPoint(size_t pointId); 16 | unsigned int* GetCellPoints(size_t cellId); 17 | private: 18 | std::vector Points; 19 | std::vector Cells; 20 | }; 21 | 22 | class Attributes 23 | { 24 | // A class for generating and storing point and cell fields. 25 | // Velocity is stored at the points and pressure is stored 26 | // for the cells. The current velocity profile is for a 27 | // shearing flow with U(y,t) = y*t, V = 0 and W = 0. 28 | // Pressure is constant through the domain. 29 | public: 30 | Attributes(); 31 | void Initialize(Grid* grid); 32 | void UpdateFields(double time); 33 | double* GetVelocityArray(); 34 | float* GetPressureArray(); 35 | 36 | private: 37 | std::vector Velocity; 38 | std::vector Pressure; 39 | Grid* GridPtr; 40 | }; 41 | #endif 42 | -------------------------------------------------------------------------------- /MPISubCommunicatorExample/FEDriver.cxx: -------------------------------------------------------------------------------- 1 | #include "FEDataStructures.h" 2 | #include 3 | #include 4 | 5 | #include "FEAdaptor.h" 6 | 7 | void SubCommunicatorDriver(int argc, char* argv[], MPI_Comm* handle) 8 | { 9 | Grid grid; 10 | unsigned int numPoints[3] = {70, 60, 44}; 11 | double spacing[3] = {1, 1.1, 1.3}; 12 | grid.Initialize(numPoints, spacing); 13 | Attributes attributes; 14 | attributes.Initialize(&grid); 15 | 16 | FEAdaptor::Initialize(argc, argv, handle); 17 | unsigned int numberOfTimeSteps = 100; 18 | for(unsigned int timeStep=0;timeStep subranks; 40 | for(int i=0;i(subranks.size())) 52 | { 53 | int newrank; 54 | MPI_Comm_rank(MPI_COMM_WORLD, &newrank); 55 | std::cout << "got a rank\n"; 56 | 57 | SubCommunicatorDriver(argc, argv, &subcommunicator); 58 | std::cout << "Process " << myrank << " did some co-processing.\n"; 59 | } 60 | else 61 | { 62 | std::cout << "Process " << myrank << " did not do any co-processing.\n"; 63 | } 64 | 65 | MPI_Finalize(); 66 | 67 | return 0; 68 | } 69 | 70 | -------------------------------------------------------------------------------- /MPISubCommunicatorExample/SampleScripts/feslicescript.py: -------------------------------------------------------------------------------- 1 | 2 | try: paraview.simple 3 | except: from paraview.simple import * 4 | 5 | from paraview import coprocessing 6 | 7 | 8 | #-------------------------------------------------------------- 9 | # Code generated from cpstate.py to create the CoProcessor. 10 | 11 | 12 | # ----------------------- CoProcessor definition ----------------------- 13 | 14 | def CreateCoProcessor(): 15 | def _CreatePipeline(coprocessor, datadescription): 16 | class Pipeline: 17 | filename_3_pvtu = coprocessor.CreateProducer( datadescription, "input" ) 18 | 19 | Slice1 = Slice( guiName="Slice1", Crinkleslice=0, SliceOffsetValues=[0.0], Triangulatetheslice=1, SliceType="Plane" ) 20 | Slice1.SliceType.Offset = 0.0 21 | Slice1.SliceType.Origin = [34.5, 32.45, 27.95] 22 | Slice1.SliceType.Normal = [1.0, 0.0, 0.0] 23 | 24 | ParallelPolyDataWriter1 = coprocessor.CreateWriter( XMLPPolyDataWriter, "slice_%t.pvtp", 10 ) 25 | 26 | SetActiveSource(filename_3_pvtu) 27 | ParallelUnstructuredGridWriter1 = coprocessor.CreateWriter( XMLPUnstructuredGridWriter, "fullgrid_%t.pvtu", 100 ) 28 | 29 | return Pipeline() 30 | 31 | class CoProcessor(coprocessing.CoProcessor): 32 | def CreatePipeline(self, datadescription): 33 | self.Pipeline = _CreatePipeline(self, datadescription) 34 | 35 | coprocessor = CoProcessor() 36 | freqs = {'input': [10, 100]} 37 | coprocessor.SetUpdateFrequencies(freqs) 38 | return coprocessor 39 | 40 | #-------------------------------------------------------------- 41 | # Global variables that will hold the pipeline for each timestep 42 | # Creating the CoProcessor object, doesn't actually create the ParaView pipeline. 43 | # It will be automatically setup when coprocessor.UpdateProducers() is called the 44 | # first time. 45 | coprocessor = CreateCoProcessor() 46 | 47 | #-------------------------------------------------------------- 48 | # Enable Live-Visualizaton with ParaView 49 | coprocessor.EnableLiveVisualization(False) 50 | 51 | 52 | # ---------------------- Data Selection method ---------------------- 53 | 54 | def RequestDataDescription(datadescription): 55 | "Callback to populate the request for current timestep" 56 | global coprocessor 57 | if datadescription.GetForceOutput() == True: 58 | # We are just going to request all fields and meshes from the simulation 59 | # code/adaptor. 60 | for i in range(datadescription.GetNumberOfInputDescriptions()): 61 | datadescription.GetInputDescription(i).AllFieldsOn() 62 | datadescription.GetInputDescription(i).GenerateMeshOn() 63 | return 64 | 65 | # setup requests for all inputs based on the requirements of the 66 | # pipeline. 67 | coprocessor.LoadRequestedData(datadescription) 68 | 69 | # ------------------------ Processing method ------------------------ 70 | 71 | def DoCoProcessing(datadescription): 72 | "Callback to do co-processing for current timestep" 73 | global coprocessor 74 | 75 | # Update the coprocessor by providing it the newly generated simulation data. 76 | # If the pipeline hasn't been setup yet, this will setup the pipeline. 77 | coprocessor.UpdateProducers(datadescription) 78 | 79 | # Write output data, if appropriate. 80 | coprocessor.WriteData(datadescription); 81 | 82 | # Write image capture (Last arg: rescale lookup table), if appropriate. 83 | coprocessor.WriteImages(datadescription, rescale_lookuptable=False) 84 | 85 | # Live Visualization, if enabled. 86 | coprocessor.DoLiveVisualization(datadescription, "localhost", 22222) 87 | -------------------------------------------------------------------------------- /PythonDolfinExample/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.8) 2 | project(CatalystCxxFullExample) 3 | 4 | find_package(ParaView 4.2 REQUIRED COMPONENTS vtkPVPythonCatalyst) 5 | include("${PARAVIEW_USE_FILE}") 6 | 7 | if(VTK_INSTALL_PREFIX) 8 | # we are in the install tree of ParaView that includes development files. 9 | # the ParaViewConfig.cmake file is located at 10 | # lib/cmake/paraview-. 11 | set(PV_MAIN_DIR ${VTK_INSTALL_PREFIX}) 12 | set(PV_MAIN_SUBDIR "paraview-${PARAVIEW_VERSION_MAJOR}.${PARAVIEW_VERSION_MINOR}") 13 | else() 14 | set(PV_MAIN_DIR ${ParaView_DIR}) 15 | endif() 16 | # The location of the ParaView and VTK libraries are set to an environment 17 | # variable that gets set in the run-catalyst-step*.sh scripts. 18 | set(LDLIBRARYPATH "${PV_MAIN_DIR}/lib/${PV_MAIN_SUBDIR}") 19 | 20 | set(DOLFIN_EXAMPLE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") 21 | set(DOLFIN_EXAMPLE_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}") 22 | set(DOLFIN_EXAMPLE_DATA_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Data") 23 | 24 | configure_file( 25 | ${CMAKE_CURRENT_SOURCE_DIR}/run-original.sh.in 26 | ${CMAKE_CURRENT_BINARY_DIR}/run-original.sh @ONLY) 27 | 28 | configure_file( 29 | ${CMAKE_CURRENT_SOURCE_DIR}/run-catalyst-step1.sh.in 30 | ${CMAKE_CURRENT_BINARY_DIR}/run-catalyst-step1.sh @ONLY) 31 | 32 | configure_file( 33 | ${CMAKE_CURRENT_SOURCE_DIR}/run-catalyst-step2.sh.in 34 | ${CMAKE_CURRENT_BINARY_DIR}/run-catalyst-step2.sh @ONLY) 35 | 36 | configure_file( 37 | ${CMAKE_CURRENT_SOURCE_DIR}/run-catalyst-step3.sh.in 38 | ${CMAKE_CURRENT_BINARY_DIR}/run-catalyst-step3.sh @ONLY) 39 | 40 | configure_file( 41 | ${CMAKE_CURRENT_SOURCE_DIR}/run-catalyst-step4.sh.in 42 | ${CMAKE_CURRENT_BINARY_DIR}/run-catalyst-step4.sh @ONLY) 43 | 44 | configure_file( 45 | ${CMAKE_CURRENT_SOURCE_DIR}/run-catalyst-step6.sh.in 46 | ${CMAKE_CURRENT_BINARY_DIR}/run-catalyst-step6.sh @ONLY) 47 | 48 | configure_file( 49 | ${CMAKE_CURRENT_SOURCE_DIR}/simulation-env.py.in 50 | ${CMAKE_CURRENT_BINARY_DIR}/simulation-env.py @ONLY) 51 | 52 | 53 | -------------------------------------------------------------------------------- /PythonDolfinExample/Data/lshape.xml.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kitware/ParaViewCatalystExampleCode-MOVED-/e5f1b521095a7ddcd6c2f51fca436368e70c85cf/PythonDolfinExample/Data/lshape.xml.gz -------------------------------------------------------------------------------- /PythonDolfinExample/README.txt: -------------------------------------------------------------------------------- 1 | [Prerequisites] 2 | Install the following packages (needs to be the version 1.3.0) 3 | dolfin-bin 4 | dolfin-dev 5 | dolfin-doc 6 | 7 | [Files] 8 | CatalystScriptTest.py 9 | a test co-processing script 10 | Data/lshape.xml.gz 11 | simulation data file, describing the mesh 12 | simulation-catalyst-step1.py 13 | simulation-catalyst-step2.py 14 | simulation-catalyst-step3.py 15 | simulation-catalyst-step4.py 16 | a solution to exercises 17 | simulation.py 18 | original dolfin python demo 19 | README.txt 20 | this file 21 | run-original.sh 22 | executes original dolfin python demo 23 | run-catalyst-step1.sh 24 | run-catalyst-step2.sh 25 | run-catalyst-step3.sh 26 | run-catalyst-step4.sh 27 | executes exercise solutions 28 | 29 | -------------------------------------------------------------------------------- /PythonDolfinExample/run-catalyst-step1.sh.in: -------------------------------------------------------------------------------- 1 | LD_LIBRARY_PATH=@LDLIBRARYPATH@:${LD_LIBRARY_PATH} \ 2 | python @DOLFIN_EXAMPLE_SOURCE_DIR@/simulation-catalyst-step1.py @DOLFIN_EXAMPLE_SOURCE_DIR@/CatalystScriptTest.py 1000 3 | -------------------------------------------------------------------------------- /PythonDolfinExample/run-catalyst-step2.sh.in: -------------------------------------------------------------------------------- 1 | LD_LIBRARY_PATH=@LDLIBRARYPATH@:${LD_LIBRARY_PATH} \ 2 | python @DOLFIN_EXAMPLE_SOURCE_DIR@/simulation-catalyst-step2.py @DOLFIN_EXAMPLE_SOURCE_DIR@/CatalystScriptTest.py 1000 3 | -------------------------------------------------------------------------------- /PythonDolfinExample/run-catalyst-step3.sh.in: -------------------------------------------------------------------------------- 1 | LD_LIBRARY_PATH=@LDLIBRARYPATH@:${LD_LIBRARY_PATH} \ 2 | python @DOLFIN_EXAMPLE_SOURCE_DIR@/simulation-catalyst-step3.py @DOLFIN_EXAMPLE_SOURCE_DIR@/CatalystScriptTest.py 1000 3 | -------------------------------------------------------------------------------- /PythonDolfinExample/run-catalyst-step4.sh.in: -------------------------------------------------------------------------------- 1 | LD_LIBRARY_PATH=@LDLIBRARYPATH@:${LD_LIBRARY_PATH} \ 2 | python @DOLFIN_EXAMPLE_SOURCE_DIR@/simulation-catalyst-step4.py @DOLFIN_EXAMPLE_SOURCE_DIR@/CatalystScriptTest.py 1000 3 | -------------------------------------------------------------------------------- /PythonDolfinExample/run-catalyst-step6.sh.in: -------------------------------------------------------------------------------- 1 | LD_LIBRARY_PATH=@LDLIBRARYPATH@:${LD_LIBRARY_PATH} \ 2 | python @DOLFIN_EXAMPLE_SOURCE_DIR@/simulation-catalyst-step6.py @DOLFIN_EXAMPLE_SOURCE_DIR@/CatalystScriptTest.py 1000 3 | -------------------------------------------------------------------------------- /PythonDolfinExample/run-original.sh.in: -------------------------------------------------------------------------------- 1 | python @DOLFIN_EXAMPLE_SOURCE_DIR@/simulation.py 2 | -------------------------------------------------------------------------------- /PythonDolfinExample/simulation-env.py.in: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | DOLFIN_EXAMPLE_DATA_DIR='@DOLFIN_EXAMPLE_DATA_DIR@' 4 | PV_MAIN_DIR='@PV_MAIN_DIR@' 5 | PV_MAIN_SUBDIR='@PV_MAIN_SUBDIR@' 6 | BUILD_DIR='@DOLFIN_EXAMPLE_BUILD_DIR@' 7 | SOURCE_DIR='@DOLFIN_EXAMPLE_SOURCE_DIR@' 8 | 9 | PV_PYTHON_PATH = [PV_MAIN_DIR+'/lib/'+PV_MAIN_SUBDIR+'/site-packages', PV_MAIN_DIR+'/lib/'+PV_MAIN_SUBDIR,PV_MAIN_DIR+'/lib/'+PV_MAIN_SUBDIR+'/site-packages/vtk'] 10 | 11 | sys.path = PV_PYTHON_PATH + sys.path 12 | 13 | -------------------------------------------------------------------------------- /PythonDolfinExample/simulation.py: -------------------------------------------------------------------------------- 1 | """This demo program solves the incompressible Navier-Stokes equations 2 | on an L-shaped domain using Chorin's splitting method.""" 3 | 4 | # Copyright (C) 2010-2011 Anders Logg 5 | # 6 | # This file is part of DOLFIN. 7 | # 8 | # DOLFIN is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU Lesser General Public License as published by 10 | # the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # DOLFIN is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU Lesser General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU Lesser General Public License 19 | # along with DOLFIN. If not, see . 20 | # 21 | # Modified by Mikael Mortensen 2011 22 | # 23 | # First added: 2010-08-30 24 | # Last changed: 2011-06-30 25 | 26 | # [SC14-Catalyst] we need a python environment that enables import of both Dolfin and ParaView 27 | execfile("simulation-env.py") 28 | 29 | # Begin demo 30 | 31 | from dolfin import * 32 | 33 | # Print log messages only from the root process in parallel 34 | parameters["std_out_all_processes"] = False; 35 | 36 | # Load mesh from file 37 | mesh = Mesh(DOLFIN_EXAMPLE_DATA_DIR+"/lshape.xml.gz") 38 | 39 | # Define function spaces (P2-P1) 40 | V = VectorFunctionSpace(mesh, "Lagrange", 2) 41 | Q = FunctionSpace(mesh, "Lagrange", 1) 42 | 43 | # Define trial and test functions 44 | u = TrialFunction(V) 45 | p = TrialFunction(Q) 46 | v = TestFunction(V) 47 | q = TestFunction(Q) 48 | 49 | # Set parameter values 50 | dt = 0.01 51 | T = 3 52 | nu = 0.01 53 | 54 | # Define time-dependent pressure boundary condition 55 | p_in = Expression("sin(3.0*t)", t=0.0) 56 | 57 | # Define boundary conditions 58 | noslip = DirichletBC(V, (0, 0), 59 | "on_boundary && \ 60 | (x[0] < DOLFIN_EPS | x[1] < DOLFIN_EPS | \ 61 | (x[0] > 0.5 - DOLFIN_EPS && x[1] > 0.5 - DOLFIN_EPS))") 62 | inflow = DirichletBC(Q, p_in, "x[1] > 1.0 - DOLFIN_EPS") 63 | outflow = DirichletBC(Q, 0, "x[0] > 1.0 - DOLFIN_EPS") 64 | bcu = [noslip] 65 | bcp = [inflow, outflow] 66 | 67 | # Create functions 68 | u0 = Function(V) 69 | u1 = Function(V) 70 | p1 = Function(Q) 71 | 72 | # Define coefficients 73 | k = Constant(dt) 74 | f = Constant((0, 0)) 75 | 76 | # Tentative velocity step 77 | F1 = (1/k)*inner(u - u0, v)*dx + inner(grad(u0)*u0, v)*dx + \ 78 | nu*inner(grad(u), grad(v))*dx - inner(f, v)*dx 79 | a1 = lhs(F1) 80 | L1 = rhs(F1) 81 | 82 | # Pressure update 83 | a2 = inner(grad(p), grad(q))*dx 84 | L2 = -(1/k)*div(u1)*q*dx 85 | 86 | # Velocity update 87 | a3 = inner(u, v)*dx 88 | L3 = inner(u1, v)*dx - k*inner(grad(p1), v)*dx 89 | 90 | # Assemble matrices 91 | A1 = assemble(a1) 92 | A2 = assemble(a2) 93 | A3 = assemble(a3) 94 | 95 | # Use amg preconditioner if available 96 | prec = "amg" if has_krylov_solver_preconditioner("amg") else "default" 97 | 98 | # Create files for storing solution 99 | ufile = File("results/velocity.pvd") 100 | pfile = File("results/pressure.pvd") 101 | 102 | # Time-stepping 103 | t = dt 104 | while t < T + DOLFIN_EPS: 105 | 106 | # Update pressure boundary condition 107 | p_in.t = t 108 | 109 | # Compute tentative velocity step 110 | begin("Computing tentative velocity") 111 | b1 = assemble(L1) 112 | [bc.apply(A1, b1) for bc in bcu] 113 | solve(A1, u1.vector(), b1, "gmres", "default") 114 | end() 115 | 116 | # Pressure correction 117 | begin("Computing pressure correction") 118 | b2 = assemble(L2) 119 | [bc.apply(A2, b2) for bc in bcp] 120 | solve(A2, p1.vector(), b2, "gmres", prec) 121 | end() 122 | 123 | # Velocity correction 124 | begin("Computing velocity correction") 125 | b3 = assemble(L3) 126 | [bc.apply(A3, b3) for bc in bcu] 127 | solve(A3, u1.vector(), b3, "gmres", "default") 128 | end() 129 | 130 | # Plot solution 131 | plot(p1, title="Pressure", rescale=True) 132 | plot(u1, title="Velocity", rescale=True) 133 | 134 | # Save to file 135 | ufile << u1 136 | pfile << p1 137 | 138 | # Move to next time step 139 | u0.assign(u1) 140 | t += dt 141 | print "t =", t 142 | 143 | # Hold plot 144 | interactive() 145 | -------------------------------------------------------------------------------- /PythonFullExample/coprocessor.py: -------------------------------------------------------------------------------- 1 | coProcessor = None 2 | usecp = True 3 | 4 | def initialize(): 5 | global coProcessor, usecp 6 | if usecp: 7 | import paraview 8 | import vtkParallelCorePython 9 | import vtk 10 | from mpi4py import MPI 11 | import os, sys 12 | 13 | paraview.options.batch = True 14 | paraview.options.symmetric = True 15 | import vtkPVClientServerCoreCorePython as CorePython 16 | try: 17 | import vtkPVServerManagerApplicationPython as ApplicationPython 18 | except: 19 | paraview.print_error("Error: Cannot import vtkPVServerManagerApplicationPython") 20 | 21 | if not CorePython.vtkProcessModule.GetProcessModule(): 22 | pvoptions = None 23 | if paraview.options.batch: 24 | pvoptions = CorePython.vtkPVOptions(); 25 | pvoptions.SetProcessType(CorePython.vtkPVOptions.PVBATCH) 26 | if paraview.options.symmetric: 27 | pvoptions.SetSymmetricMPIMode(True) 28 | ApplicationPython.vtkInitializationHelper.Initialize(sys.executable, CorePython.vtkProcessModule.PROCESS_BATCH, pvoptions) 29 | 30 | import paraview.servermanager as pvsm 31 | # we need ParaView 4.2 since ParaView 4.1 doesn't properly wrap 32 | # vtkPVPythonCatalystPython 33 | if pvsm.vtkSMProxyManager.GetVersionMajor() != 4 or \ 34 | pvsm.vtkSMProxyManager.GetVersionMinor() < 2: 35 | print 'Must use ParaView v4.2 or greater' 36 | sys.exit(0) 37 | 38 | import numpy 39 | import vtkPVCatalystPython as catalyst 40 | import vtkPVPythonCatalystPython as pythoncatalyst 41 | import paraview.simple 42 | import paraview.vtk as vtk 43 | from paraview import numpy_support 44 | paraview.options.batch = True 45 | paraview.options.symmetric = True 46 | 47 | coProcessor = catalyst.vtkCPProcessor() 48 | pm = paraview.servermanager.vtkProcessModule.GetProcessModule() 49 | from mpi4py import MPI 50 | 51 | def finalize(): 52 | global coProcessor, usecp 53 | if usecp: 54 | coProcessor.Finalize() 55 | import vtkPVServerManagerApplicationPython as ApplicationPython 56 | ApplicationPython.vtkInitializationHelper.Finalize() 57 | 58 | def addscript(name): 59 | global coProcessor 60 | import vtkPVPythonCatalystPython as pythoncatalyst 61 | pipeline = pythoncatalyst.vtkCPPythonScriptPipeline() 62 | pipeline.Initialize(name) 63 | coProcessor.AddPipeline(pipeline) 64 | 65 | def coprocess(time, timeStep, grid, attributes): 66 | global coProcessor 67 | import vtk 68 | import vtkPVCatalystPython as catalyst 69 | import paraview 70 | from paraview import numpy_support 71 | dataDescription = catalyst.vtkCPDataDescription() 72 | dataDescription.SetTimeData(time, timeStep) 73 | dataDescription.AddInput("input") 74 | 75 | if coProcessor.RequestDataDescription(dataDescription): 76 | import fedatastructures 77 | imageData = vtk.vtkImageData() 78 | imageData.SetExtent(grid.XStartPoint, grid.XEndPoint, 0, grid.NumberOfYPoints-1, 0, grid.NumberOfZPoints-1) 79 | imageData.SetSpacing(grid.Spacing) 80 | 81 | velocity = paraview.numpy_support.numpy_to_vtk(attributes.Velocity) 82 | velocity.SetName("velocity") 83 | imageData.GetPointData().AddArray(velocity) 84 | 85 | pressure = numpy_support.numpy_to_vtk(attributes.Pressure) 86 | pressure.SetName("pressure") 87 | imageData.GetCellData().AddArray(pressure) 88 | dataDescription.GetInputDescriptionByName("input").SetGrid(imageData) 89 | dataDescription.GetInputDescriptionByName("input").SetWholeExtent(0, grid.NumberOfGlobalXPoints-1, 0, grid.NumberOfYPoints-1, 0, grid.NumberOfZPoints-1) 90 | coProcessor.CoProcess(dataDescription) 91 | 92 | 93 | -------------------------------------------------------------------------------- /PythonFullExample/cpscript.py: -------------------------------------------------------------------------------- 1 | try: paraview.simple 2 | except: from paraview.simple import * 3 | 4 | from paraview import coprocessing 5 | 6 | 7 | #-------------------------------------------------------------- 8 | # Code generated from cpstate.py to create the CoProcessor. 9 | 10 | 11 | # ----------------------- CoProcessor definition ----------------------- 12 | 13 | def CreateCoProcessor(): 14 | def _CreatePipeline(coprocessor, datadescription): 15 | class Pipeline: 16 | filename_6_pvti = coprocessor.CreateProducer( datadescription, "input" ) 17 | 18 | ParallelImageDataWriter1 = coprocessor.CreateWriter( XMLPImageDataWriter, "fullgrid_%t.pvti", 100 ) 19 | 20 | SetActiveSource(filename_6_pvti) 21 | Slice1 = Slice( guiName="Slice1", Crinkleslice=0, SliceOffsetValues=[0.0], Triangulatetheslice=1, SliceType="Plane" ) 22 | Slice1.SliceType.Offset = 0.0 23 | Slice1.SliceType.Origin = [9.0, 11.0, 9.0] 24 | Slice1.SliceType.Normal = [1.0, 0.0, 0.0] 25 | 26 | ParallelPolyDataWriter1 = coprocessor.CreateWriter( XMLPPolyDataWriter, "slice_%t.pvtp", 10 ) 27 | 28 | return Pipeline() 29 | 30 | class CoProcessor(coprocessing.CoProcessor): 31 | def CreatePipeline(self, datadescription): 32 | self.Pipeline = _CreatePipeline(self, datadescription) 33 | 34 | coprocessor = CoProcessor() 35 | freqs = {'input': [10, 100]} 36 | coprocessor.SetUpdateFrequencies(freqs) 37 | return coprocessor 38 | 39 | #-------------------------------------------------------------- 40 | # Global variables that will hold the pipeline for each timestep 41 | # Creating the CoProcessor object, doesn't actually create the ParaView pipeline. 42 | # It will be automatically setup when coprocessor.UpdateProducers() is called the 43 | # first time. 44 | coprocessor = CreateCoProcessor() 45 | 46 | #-------------------------------------------------------------- 47 | # Enable Live-Visualizaton with ParaView 48 | coprocessor.EnableLiveVisualization(False, 1) 49 | 50 | 51 | # ---------------------- Data Selection method ---------------------- 52 | 53 | def RequestDataDescription(datadescription): 54 | "Callback to populate the request for current timestep" 55 | global coprocessor 56 | if datadescription.GetForceOutput() == True: 57 | # We are just going to request all fields and meshes from the simulation 58 | # code/adaptor. 59 | for i in range(datadescription.GetNumberOfInputDescriptions()): 60 | datadescription.GetInputDescription(i).AllFieldsOn() 61 | datadescription.GetInputDescription(i).GenerateMeshOn() 62 | return 63 | 64 | # setup requests for all inputs based on the requirements of the 65 | # pipeline. 66 | coprocessor.LoadRequestedData(datadescription) 67 | 68 | # ------------------------ Processing method ------------------------ 69 | 70 | def DoCoProcessing(datadescription): 71 | "Callback to do co-processing for current timestep" 72 | global coprocessor 73 | 74 | # Update the coprocessor by providing it the newly generated simulation data. 75 | # If the pipeline hasn't been setup yet, this will setup the pipeline. 76 | coprocessor.UpdateProducers(datadescription) 77 | 78 | # Write output data, if appropriate. 79 | coprocessor.WriteData(datadescription); 80 | 81 | # Write image capture (Last arg: rescale lookup table), if appropriate. 82 | coprocessor.WriteImages(datadescription, rescale_lookuptable=False) 83 | 84 | # Live Visualization, if enabled. 85 | coprocessor.DoLiveVisualization(datadescription, "localhost", 22222) 86 | -------------------------------------------------------------------------------- /PythonFullExample/fedatastructures.py: -------------------------------------------------------------------------------- 1 | import numpy 2 | 3 | class GridClass: 4 | """ 5 | We are working with a uniform grid which will be 6 | represented as a vtkImageData in Catalyst. It is partitioned 7 | in the x-direction only. 8 | """ 9 | def __init__(self, pointDimensions, spacing): 10 | from mpi4py import MPI 11 | comm = MPI.COMM_WORLD 12 | rank = comm.Get_rank() 13 | size = comm.Get_size() 14 | 15 | self.XStartPoint = int(pointDimensions[0]*rank/size) 16 | self.XEndPoint = int(pointDimensions[0]*(rank+1)/size) 17 | if rank+1 != size: 18 | self.XEndPoint += 1 19 | else: 20 | self.XEndPoint = pointDimensions[0]-1 21 | self.NumberOfYPoints = pointDimensions[1] 22 | self.NumberOfZPoints = pointDimensions[2] 23 | self.NumberOfGlobalXPoints = pointDimensions[0] 24 | 25 | self.PointDimensions = pointDimensions 26 | self.Spacing = spacing 27 | 28 | def GetNumberOfPoints(self): 29 | return (self.XEndPoint-self.XStartPoint+1)*self.PointDimensions[1]*self.PointDimensions[2] 30 | 31 | def GetNumberOfCells(self): 32 | return (self.XEndPoint-self.XStartPoint)*(self.PointDimensions[1]-1)*(self.PointDimensions[2]-1) 33 | 34 | class AttributesClass: 35 | """ 36 | We have velocity point data and pressure cell data. 37 | """ 38 | def __init__(self, grid): 39 | self.Grid = grid 40 | 41 | def Update(self, time): 42 | self.Velocity = numpy.zeros((self.Grid.GetNumberOfPoints(), 3)) 43 | self.Velocity = self.Velocity + time 44 | self.Pressure = numpy.zeros(self.Grid.GetNumberOfCells()) 45 | -------------------------------------------------------------------------------- /PythonFullExample/fedriver.py: -------------------------------------------------------------------------------- 1 | """ 2 | A simple example of a Python simulation code working with Catalyst. 3 | It depends on numpy and mpi4py being available. The environment 4 | variables need to be set up properly to find Catalyst. For Linux 5 | and Mac machines they should be: 6 | export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/lib 7 | export PYTHONPATH=/lib:/lib/site-packages 8 | """ 9 | import numpy 10 | import sys 11 | from mpi4py import MPI 12 | 13 | comm = MPI.COMM_WORLD 14 | rank = comm.Get_rank() 15 | 16 | import fedatastructures 17 | 18 | grid = fedatastructures.GridClass([10, 12, 10], [2, 2, 2]) 19 | attributes = fedatastructures.AttributesClass(grid) 20 | doCoprocessing = True 21 | 22 | if doCoprocessing: 23 | import coprocessor 24 | coprocessor.initialize() 25 | coprocessor.addscript("cpscript.py") 26 | 27 | for i in range(100): 28 | attributes.Update(i) 29 | if doCoprocessing: 30 | import coprocessor 31 | coprocessor.coprocess(i, i, grid, attributes) 32 | 33 | if doCoprocessing: 34 | import coprocessor 35 | coprocessor.finalize() 36 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | NOTE: These examples have been moved into the main ParaView repository and 2 | are available at https://gitlab.kitware.com/paraview/paraview under the Examples/Catalyst 3 | subdirectory. 4 | 5 | This repository gives examples of how to use ParaView Catalyst (catalyst.paraview.org) 6 | for in situ analysis and visualization. For assistance, please email the ParaView 7 | mailing list at paraview@paraview.org. The examples show how to create VTK data 8 | structures from native simulation code data structures, how to interface to ParaView 9 | Catalyst and how to set up several different types of pipelines. The examples can 10 | either be built individually or as a group. Many work in parallel as well. The tests 11 | are very simple and just verify that the examples run -- they don't not verify 12 | correctness of outputs. A description of the examples are: 13 | * FortranPoissonSolver -- An example of a parallel, finite difference discretization of the Poisson equation 14 | implemented in Fortran using a Conjugate Gradient solver. Instead of co-processing 15 | at the end of each time step it co-processes at the end of each iteration. 16 | * Fortran90FullExample -- An example of a simulation code written in Fortran 17 | that is linked with Catalyst. 18 | * CFullExample -- An example of a simulation code written in C. This uses some 19 | methods from Catalyst for storing VTK data structures. This 20 | assumes a vtkUnstructuredGrid. 21 | * CFullExample2 -- An example of a simulation code written in C. This improves 22 | upon the CFullExample by explictly storing VTK data structures. 23 | This assumes a vtkUnstructuredGrid. 24 | * CxxFullExample -- A C++ example of a simulation code interfacing with Catalyst. 25 | This assumes a vtkUnstructuredGrid. 26 | * PythonFullExample -- An example of a simulation code written in Python 27 | that uses Catalyst. 28 | * PythonDolfinExample -- An example that uses the Dolfin simulation code. 29 | * CxxImageDataExample -- A C++ example of a simulation code interfacing with 30 | Catalyst. The grid is a vtkImageData. 31 | * CxxMultiPieceExample -- A C++ example of a simulation code interfacing with 32 | Catalyst. The grid is a vtkMultiPiece data set with 33 | a single vtkImageData for each process. 34 | * CxxNonOverlappingAMRExample -- A C++ example of a simulation code interfacing with 35 | Catalyst. The grid is a vtkNonOverlappingAMR.h 36 | data set. 37 | * CxxOverlappingAMRExample -- A C++ example of a simulation code interfacing with 38 | Catalyst. The grid is a vtkOverlappingAMR.h 39 | data set. 40 | * CxxPVSMPipelineExample -- An example where we manually create a Catalyst 41 | pipeline in C++ code using ParaView's server-manager. 42 | This example can be run without ParaView being built 43 | with Python. 44 | * CxxVTKPipelineExample -- An example where we manually create a Catalyst 45 | pipeline in C++ code using VTK filters. 46 | This example can be run without ParaView being built 47 | with Python. 48 | * CxxMappedDataArrayExample -- An example of an adaptor where we use VTK mapped 49 | arrays to map simulation data structures to 50 | VTK data arrays to save on memory use by Catalyst. 51 | * MPISubCommunicatorExample -- An example where only a subset of the MPI 52 | processes are used for the simulation and Catalyst. 53 | 54 | Other objects of interest: 55 | * LICENSE.md -- The license of this software. 56 | * SampleScripts -- A directory with some useful sample Catalyst Python pipelines. 57 | Currently the only file in this is a script that writes out 58 | the entire "input" grid at each time step. This can be useful 59 | for creating other Catalyst Python pipelines with the 60 | co-processing plugin in the ParaView GUI. 61 | * CMakeLists.txt -- The file used to build all of the examples in a single shot. 62 | -------------------------------------------------------------------------------- /SampleScripts/allinputsgridwriter.py: -------------------------------------------------------------------------------- 1 | from paraview.simple import * 2 | 3 | from paraview import coprocessing 4 | 5 | # the frequency to output everything 6 | outputfrequency = 5 7 | 8 | # the name of the inputs that the adaptor provides 9 | # for most it will just be 'input' by convention 10 | namedinputs = ['input'] 11 | 12 | # ----------------------- CoProcessor definition ----------------------- 13 | 14 | def CreateCoProcessor(): 15 | def _CreatePipeline(coprocessor, datadescription): 16 | class Pipeline: 17 | for name in namedinputs: 18 | inputdescription = datadescription.GetInputDescriptionByName(name) 19 | adaptorinput = coprocessor.CreateProducer( datadescription, name ) 20 | grid = adaptorinput.GetClientSideObject().GetOutputDataObject(0) 21 | if grid.IsA('vtkImageData') or grid.IsA('vtkUniformGrid'): 22 | writer = coprocessor.CreateWriter( XMLPImageDataWriter, name+"_%t.pvti", outputfrequency ) 23 | elif grid.IsA('vtkRectilinearGrid'): 24 | writer = coprocessor.CreateWriter( XMLPRectilinearGridWriter, name+"_%t.pvtr", outputfrequency ) 25 | elif grid.IsA('vtkStructuredGrid'): 26 | writer = coprocessor.CreateWriter( XMLPStructuredGridWriter, name+"_%t.pvts", outputfrequency ) 27 | elif grid.IsA('vtkPolyData'): 28 | writer = coprocessor.CreateWriter( XMLPPolyDataWriter, name+"_%t.pvtp", outputfrequency ) 29 | elif grid.IsA('vtkUnstructuredGrid'): 30 | writer = coprocessor.CreateWriter( XMLPUnstructuredGridWriter, name+"_%t.pvtu", outputfrequency ) 31 | elif grid.IsA('vtkUniformGridAMR'): 32 | writer = coprocessor.CreateWriter( XMLHierarchicalBoxDataWriter, name+"_%t.vthb", outputfrequency ) 33 | elif grid.IsA('vtkMultiBlockDataSet'): 34 | writer = coprocessor.CreateWriter( XMLMultiBlockDataWriter, name+"_%t.vtm", outputfrequency ) 35 | else: 36 | print "Don't know how to create a writer for a ", grid.GetClassName() 37 | 38 | return Pipeline() 39 | 40 | class CoProcessor(coprocessing.CoProcessor): 41 | def CreatePipeline(self, datadescription): 42 | self.Pipeline = _CreatePipeline(self, datadescription) 43 | 44 | coprocessor = CoProcessor() 45 | freqs = {} 46 | for name in namedinputs: 47 | freqs[name] = [outputfrequency] 48 | 49 | coprocessor.SetUpdateFrequencies(freqs) 50 | return coprocessor 51 | 52 | #-------------------------------------------------------------- 53 | # Global variables that will hold the pipeline for each timestep 54 | # Creating the CoProcessor object, doesn't actually create the ParaView pipeline. 55 | # It will be automatically setup when coprocessor.UpdateProducers() is called the 56 | # first time. 57 | coprocessor = CreateCoProcessor() 58 | 59 | #-------------------------------------------------------------- 60 | # Enable Live-Visualizaton with ParaView 61 | coprocessor.EnableLiveVisualization(False) 62 | 63 | 64 | # ---------------------- Data Selection method ---------------------- 65 | 66 | def RequestDataDescription(datadescription): 67 | "Callback to populate the request for current timestep" 68 | global coprocessor 69 | if datadescription.GetForceOutput() == True: 70 | # We are just going to request all fields and meshes from the simulation 71 | # code/adaptor. 72 | for i in range(datadescription.GetNumberOfInputDescriptions()): 73 | datadescription.GetInputDescription(i).AllFieldsOn() 74 | datadescription.GetInputDescription(i).GenerateMeshOn() 75 | return 76 | 77 | # setup requests for all inputs based on the requirements of the 78 | # pipeline. 79 | coprocessor.LoadRequestedData(datadescription) 80 | 81 | # ------------------------ Processing method ------------------------ 82 | 83 | def DoCoProcessing(datadescription): 84 | "Callback to do co-processing for current timestep" 85 | global coprocessor 86 | 87 | # Update the coprocessor by providing it the newly generated simulation data. 88 | # If the pipeline hasn't been setup yet, this will setup the pipeline. 89 | coprocessor.UpdateProducers(datadescription) 90 | 91 | # Write output data, if appropriate. 92 | coprocessor.WriteData(datadescription); 93 | 94 | # Write image capture (Last arg: rescale lookup table), if appropriate. 95 | coprocessor.WriteImages(datadescription, rescale_lookuptable=False) 96 | 97 | # Live Visualization, if enabled. 98 | coprocessor.DoLiveVisualization(datadescription, "localhost", 22222) 99 | -------------------------------------------------------------------------------- /SampleScripts/gridwriter.py: -------------------------------------------------------------------------------- 1 | from paraview.simple import * 2 | 3 | from paraview import coprocessing 4 | 5 | 6 | #-------------------------------------------------------------- 7 | # Code generated from cpstate.py to create the CoProcessor. 8 | 9 | 10 | # ----------------------- CoProcessor definition ----------------------- 11 | 12 | def CreateCoProcessor(): 13 | def _CreatePipeline(coprocessor, datadescription): 14 | class Pipeline: 15 | adaptorinput = coprocessor.CreateProducer( datadescription, "input" ) 16 | grid = adaptorinput.GetClientSideObject().GetOutputDataObject(0) 17 | if grid.IsA('vtkImageData') or grid.IsA('vtkUniformGrid'): 18 | writer = coprocessor.CreateWriter( XMLPImageDataWriter, "filename_%t.pvti", 1 ) 19 | elif grid.IsA('vtkRectilinearGrid'): 20 | writer = coprocessor.CreateWriter( XMLPRectilinearGridWriter, "filename_%t.pvtr", 1 ) 21 | elif grid.IsA('vtkStructuredGrid'): 22 | writer = coprocessor.CreateWriter( XMLPStructuredGridWriter, "filename_%t.pvts", 1 ) 23 | elif grid.IsA('vtkPolyData'): 24 | writer = coprocessor.CreateWriter( XMLPPolyDataWriter, "filename_%t.pvtp", 1 ) 25 | elif grid.IsA('vtkUnstructuredGrid'): 26 | writer = coprocessor.CreateWriter( XMLPUnstructuredGridWriter, "filename_%t.pvtu", 1 ) 27 | elif grid.IsA('vtkUniformGridAMR'): 28 | writer = coprocessor.CreateWriter( XMLHierarchicalBoxDataWriter, "filename_%t.vthb", 1 ) 29 | elif grid.IsA('vtkMultiBlockDataSet'): 30 | writer = coprocessor.CreateWriter( XMLMultiBlockDataWriter, "filename_%t.vtm", 1 ) 31 | else: 32 | print "Don't know how to create a writer for a ", grid.GetClassName() 33 | 34 | return Pipeline() 35 | 36 | class CoProcessor(coprocessing.CoProcessor): 37 | def CreatePipeline(self, datadescription): 38 | self.Pipeline = _CreatePipeline(self, datadescription) 39 | 40 | coprocessor = CoProcessor() 41 | freqs = {'input': [1]} 42 | coprocessor.SetUpdateFrequencies(freqs) 43 | return coprocessor 44 | 45 | #-------------------------------------------------------------- 46 | # Global variables that will hold the pipeline for each timestep 47 | # Creating the CoProcessor object, doesn't actually create the ParaView pipeline. 48 | # It will be automatically setup when coprocessor.UpdateProducers() is called the 49 | # first time. 50 | coprocessor = CreateCoProcessor() 51 | 52 | #-------------------------------------------------------------- 53 | # Enable Live-Visualizaton with ParaView 54 | coprocessor.EnableLiveVisualization(False) 55 | 56 | 57 | # ---------------------- Data Selection method ---------------------- 58 | 59 | def RequestDataDescription(datadescription): 60 | "Callback to populate the request for current timestep" 61 | global coprocessor 62 | if datadescription.GetForceOutput() == True: 63 | # We are just going to request all fields and meshes from the simulation 64 | # code/adaptor. 65 | for i in range(datadescription.GetNumberOfInputDescriptions()): 66 | datadescription.GetInputDescription(i).AllFieldsOn() 67 | datadescription.GetInputDescription(i).GenerateMeshOn() 68 | return 69 | 70 | # setup requests for all inputs based on the requirements of the 71 | # pipeline. 72 | coprocessor.LoadRequestedData(datadescription) 73 | 74 | # ------------------------ Processing method ------------------------ 75 | 76 | def DoCoProcessing(datadescription): 77 | "Callback to do co-processing for current timestep" 78 | global coprocessor 79 | 80 | # Update the coprocessor by providing it the newly generated simulation data. 81 | # If the pipeline hasn't been setup yet, this will setup the pipeline. 82 | coprocessor.UpdateProducers(datadescription) 83 | 84 | # Write output data, if appropriate. 85 | coprocessor.WriteData(datadescription); 86 | 87 | # Write image capture (Last arg: rescale lookup table), if appropriate. 88 | coprocessor.WriteImages(datadescription, rescale_lookuptable=False) 89 | 90 | # Live Visualization, if enabled. 91 | coprocessor.DoLiveVisualization(datadescription, "localhost", 22222) 92 | --------------------------------------------------------------------------------