mirror of
https://github.com/OpenFOAM/ThirdParty-6.git
synced 2025-12-08 06:57:43 +00:00
ParaView-5.0.1: Added the source-tree to ThirdParty-dev and patched as described in the README file
Resolves bug-report http://bugs.openfoam.org/view.php?id=2098
This commit is contained in:
@ -0,0 +1,58 @@
|
||||
cmake_minimum_required(VERSION 2.8.8)
|
||||
project(CatalystCxxParticlePathExample)
|
||||
|
||||
set(USE_CATALYST ON CACHE BOOL "Link the simulator with Catalyst")
|
||||
if(USE_CATALYST)
|
||||
# we need 5.0 for the proper in situ particle path filter
|
||||
find_package(ParaView 5.0 REQUIRED COMPONENTS vtkPVPythonCatalyst)
|
||||
include("${PARAVIEW_USE_FILE}")
|
||||
set(Adaptor_SRCS
|
||||
FEAdaptor.cxx
|
||||
)
|
||||
add_library(CxxParticlePathExampleAdaptor ${Adaptor_SRCS})
|
||||
target_link_libraries(CxxParticlePathExampleAdaptor vtkPVPythonCatalyst vtkParallelMPI)
|
||||
add_definitions("-DUSE_CATALYST")
|
||||
if(NOT PARAVIEW_USE_MPI)
|
||||
message(SEND_ERROR "ParaView must be built with MPI enabled")
|
||||
endif()
|
||||
else()
|
||||
find_package(MPI REQUIRED)
|
||||
include_directories(${MPI_C_INCLUDE_PATH})
|
||||
endif()
|
||||
|
||||
add_executable(CxxParticlePathExample FEDriver.cxx FEDataStructures.cxx)
|
||||
if(USE_CATALYST)
|
||||
target_link_libraries(CxxParticlePathExample LINK_PRIVATE CxxParticlePathExampleAdaptor)
|
||||
include(vtkModuleMacros)
|
||||
include(vtkMPI)
|
||||
vtk_mpi_link(CxxParticlePathExample)
|
||||
else()
|
||||
target_link_libraries(CxxParticlePathExample LINK_PRIVATE ${MPI_LIBRARIES})
|
||||
endif()
|
||||
|
||||
option(BUILD_TESTING "Build Testing" OFF)
|
||||
# Setup testing.
|
||||
if (BUILD_TESTING)
|
||||
include(CTest)
|
||||
|
||||
if(PARAVIEW_TEST_OUTPUT_DIR)
|
||||
set(TEST_OUTPUT_DIR ${PARAVIEW_TEST_OUTPUT_DIR})
|
||||
else(PARAVIEW_TEST_OUTPUT_DIR)
|
||||
set(TEST_OUTPUT_DIR "${CMAKE_BINARY_DIR}/Testing/Temporary")
|
||||
endif(PARAVIEW_TEST_OUTPUT_DIR)
|
||||
|
||||
add_test(NAME CxxParticlePathExampleTest
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DCOPROCESSING_TEST_DRIVER:FILEPATH=$<TARGET_FILE:CxxParticlePathExample>
|
||||
-DCOPROCESSING_TEST_DIR:PATH=${TEST_OUTPUT_DIR}
|
||||
-DCOPROCESSING_SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}
|
||||
-DPVBATCH:FILEPATH=$<TARGET_FILE:pvbatch>
|
||||
-DMPIEXEC:FILEPATH=${MPIEXEC}
|
||||
-DMPIEXEC_NUMPROC_FLAG:STRING=${MPIEXEC_NUMPROC_FLAG}
|
||||
-DMPIEXEC_NUMPROCS=4
|
||||
-DMPIEXEC_PREFLAGS:STRING=${MPIEXEC_PREFLAGS}
|
||||
-DVTK_MPI_POSTFLAGS:STRING=${VTK_MPI_POSTFLAGS}
|
||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/ParticlePathTesting.cmake)
|
||||
set_tests_properties(CxxParticlePathExampleTest PROPERTIES LABELS "PARAVIEW;CATALYST")
|
||||
|
||||
endif (BUILD_TESTING)
|
||||
@ -0,0 +1,142 @@
|
||||
#include <iostream>
|
||||
#include "FEAdaptor.h"
|
||||
#include "FEDataStructures.h"
|
||||
|
||||
#include <vtkCellData.h>
|
||||
#include <vtkCellType.h>
|
||||
#include <vtkCPDataDescription.h>
|
||||
#include <vtkCPInputDataDescription.h>
|
||||
#include <vtkCPProcessor.h>
|
||||
#include <vtkCPPythonScriptPipeline.h>
|
||||
#include <vtkDoubleArray.h>
|
||||
#include <vtkFloatArray.h>
|
||||
#include <vtkNew.h>
|
||||
#include <vtkPoints.h>
|
||||
#include <vtkPointData.h>
|
||||
#include <vtkUnstructuredGrid.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
vtkCPProcessor* Processor = NULL;
|
||||
|
||||
void BuildVTKGrid(Grid& grid, vtkUnstructuredGrid* vtkgrid)
|
||||
{
|
||||
// create the points information
|
||||
vtkNew<vtkDoubleArray> pointArray;
|
||||
pointArray->SetNumberOfComponents(3);
|
||||
pointArray->SetArray(grid.GetPointsArray(), static_cast<vtkIdType>(grid.GetNumberOfPoints()*3), 1);
|
||||
vtkNew<vtkPoints> points;
|
||||
points->SetData(pointArray.GetPointer());
|
||||
vtkgrid->SetPoints(points.GetPointer());
|
||||
|
||||
// create the cells
|
||||
size_t numCells = grid.GetNumberOfCells();
|
||||
vtkgrid->Allocate(static_cast<vtkIdType>(numCells*9));
|
||||
for(size_t cell=0;cell<numCells;cell++)
|
||||
{
|
||||
unsigned int* cellPoints = grid.GetCellPoints(cell);
|
||||
vtkIdType tmp[8] = {cellPoints[0], cellPoints[1], cellPoints[2], cellPoints[3],
|
||||
cellPoints[4], cellPoints[5], cellPoints[6], cellPoints[7]};
|
||||
vtkgrid->InsertNextCell(VTK_HEXAHEDRON, 8, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateVTKAttributes(Grid& grid, Attributes& attributes, vtkUnstructuredGrid* vtkgrid)
|
||||
{
|
||||
if(vtkgrid->GetPointData()->GetNumberOfArrays() == 0)
|
||||
{
|
||||
// velocity array
|
||||
vtkNew<vtkDoubleArray> velocity;
|
||||
velocity->SetName("velocity");
|
||||
velocity->SetNumberOfComponents(3);
|
||||
velocity->SetNumberOfTuples(static_cast<vtkIdType>(grid.GetNumberOfPoints()));
|
||||
vtkgrid->GetPointData()->AddArray(velocity.GetPointer());
|
||||
}
|
||||
if(vtkgrid->GetCellData()->GetNumberOfArrays() == 0)
|
||||
{
|
||||
// pressure array
|
||||
vtkNew<vtkFloatArray> pressure;
|
||||
pressure->SetName("pressure");
|
||||
pressure->SetNumberOfComponents(1);
|
||||
vtkgrid->GetCellData()->AddArray(pressure.GetPointer());
|
||||
}
|
||||
vtkDoubleArray* velocity = vtkDoubleArray::SafeDownCast(
|
||||
vtkgrid->GetPointData()->GetArray("velocity"));
|
||||
// The velocity array is ordered as vx0,vx1,vx2,..,vy0,vy1,vy2,..,vz0,vz1,vz2,..
|
||||
// so we need to create a full copy of it with VTK's ordering of
|
||||
// vx0,vy0,vz0,vx1,vy1,vz1,..
|
||||
double* velocityData = attributes.GetVelocityArray();
|
||||
vtkIdType numTuples = velocity->GetNumberOfTuples();
|
||||
for(vtkIdType i=0;i<numTuples;i++)
|
||||
{
|
||||
double values[3] = {velocityData[i], velocityData[i+numTuples],
|
||||
velocityData[i+2*numTuples]};
|
||||
velocity->SetTupleValue(i, values);
|
||||
}
|
||||
|
||||
vtkFloatArray* pressure = vtkFloatArray::SafeDownCast(
|
||||
vtkgrid->GetCellData()->GetArray("pressure"));
|
||||
// The pressure array is a scalar array so we can reuse
|
||||
// memory as long as we ordered the points properly.
|
||||
float* pressureData = attributes.GetPressureArray();
|
||||
pressure->SetArray(pressureData, static_cast<vtkIdType>(grid.GetNumberOfCells()), 1);
|
||||
}
|
||||
|
||||
void BuildVTKDataStructures(Grid& grid, Attributes& attributes, vtkUnstructuredGrid* vtkgrid)
|
||||
{
|
||||
BuildVTKGrid(grid, vtkgrid);
|
||||
UpdateVTKAttributes(grid, attributes, vtkgrid);
|
||||
}
|
||||
}
|
||||
|
||||
namespace FEAdaptor
|
||||
{
|
||||
void Initialize(std::vector<std::string>& scripts)
|
||||
{
|
||||
if(Processor == NULL)
|
||||
{
|
||||
Processor = vtkCPProcessor::New();
|
||||
Processor->Initialize();
|
||||
}
|
||||
else
|
||||
{
|
||||
Processor->RemoveAllPipelines();
|
||||
}
|
||||
for(std::vector<std::string>::iterator it=scripts.begin();it!=scripts.end();it++)
|
||||
{
|
||||
vtkNew<vtkCPPythonScriptPipeline> pipeline;
|
||||
pipeline->Initialize(it->c_str());
|
||||
Processor->AddPipeline(pipeline.GetPointer());
|
||||
}
|
||||
}
|
||||
|
||||
void Finalize()
|
||||
{
|
||||
if(Processor)
|
||||
{
|
||||
Processor->Delete();
|
||||
Processor = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void CoProcess(Grid& grid, Attributes& attributes, double time,
|
||||
unsigned int timeStep, bool lastTimeStep)
|
||||
{
|
||||
vtkNew<vtkCPDataDescription> dataDescription;
|
||||
dataDescription->AddInput("input");
|
||||
dataDescription->SetTimeData(time, timeStep);
|
||||
if(lastTimeStep == true)
|
||||
{
|
||||
// assume that we want to all the pipelines to execute if it
|
||||
// is the last time step.
|
||||
dataDescription->ForceOutputOn();
|
||||
}
|
||||
if(Processor->RequestDataDescription(dataDescription.GetPointer()) != 0)
|
||||
{
|
||||
vtkNew<vtkUnstructuredGrid> vtkgrid;
|
||||
BuildVTKDataStructures(grid, attributes, vtkgrid.GetPointer());
|
||||
dataDescription->GetInputDescriptionByName("input")->SetGrid(vtkgrid.GetPointer());
|
||||
Processor->CoProcess(dataDescription.GetPointer());
|
||||
}
|
||||
}
|
||||
} // end of Catalyst namespace
|
||||
@ -0,0 +1,20 @@
|
||||
#ifndef FEADAPTOR_HEADER
|
||||
#define FEADAPTOR_HEADER
|
||||
|
||||
class Attributes;
|
||||
class Grid;
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace FEAdaptor
|
||||
{
|
||||
void Initialize(std::vector<std::string>& scripts);
|
||||
|
||||
void Finalize();
|
||||
|
||||
void CoProcess(Grid& grid, Attributes& attributes, double time,
|
||||
unsigned int timeStep, bool lastTimeStep);
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,154 @@
|
||||
#include "FEDataStructures.h"
|
||||
|
||||
#include <mpi.h>
|
||||
#include <iostream>
|
||||
|
||||
Grid::Grid()
|
||||
{}
|
||||
|
||||
void Grid::Initialize(const unsigned int numPoints[3], const double spacing[3] )
|
||||
{
|
||||
if(numPoints[0] == 0 || numPoints[1] == 0 || numPoints[2] == 0)
|
||||
{
|
||||
std::cerr << "Must have a non-zero amount of points in each direction.\n";
|
||||
}
|
||||
// in parallel, we do a simple partitioning in the x-direction.
|
||||
int mpiSize = 1;
|
||||
int mpiRank = 0;
|
||||
MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
|
||||
MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
|
||||
|
||||
unsigned int startXPoint = mpiRank*numPoints[0]/mpiSize;
|
||||
unsigned int endXPoint = (mpiRank+1)*numPoints[0]/mpiSize;
|
||||
if(mpiSize != mpiRank+1)
|
||||
{
|
||||
endXPoint++;
|
||||
}
|
||||
|
||||
// create the points -- slowest in the x and fastest in the z directions
|
||||
double coord[3] = {0,0,0};
|
||||
for(unsigned int i=startXPoint;i<endXPoint;i++)
|
||||
{
|
||||
coord[0] = i*spacing[0];
|
||||
for(unsigned int j=0;j<numPoints[1];j++)
|
||||
{
|
||||
coord[1] = j*spacing[1];
|
||||
for(unsigned int k=0;k<numPoints[2];k++)
|
||||
{
|
||||
coord[2] = k*spacing[2];
|
||||
// add the coordinate to the end of the vector
|
||||
std::copy(coord, coord+3, std::back_inserter(this->Points));
|
||||
}
|
||||
}
|
||||
}
|
||||
// create the hex cells
|
||||
unsigned int cellPoints[8];
|
||||
unsigned int numXPoints = endXPoint - startXPoint;
|
||||
for(unsigned int i=0;i<numXPoints-1;i++)
|
||||
{
|
||||
for(unsigned int j=0;j<numPoints[1]-1;j++)
|
||||
{
|
||||
for(unsigned int k=0;k<numPoints[2]-1;k++)
|
||||
{
|
||||
cellPoints[0] = i*numPoints[1]*numPoints[2] +
|
||||
j*numPoints[2] + k;
|
||||
cellPoints[1] = (i+1)*numPoints[1]*numPoints[2] +
|
||||
j*numPoints[2] + k;
|
||||
cellPoints[2] = (i+1)*numPoints[1]*numPoints[2] +
|
||||
(j+1)*numPoints[2] + k;
|
||||
cellPoints[3] = i*numPoints[1]*numPoints[2] +
|
||||
(j+1)*numPoints[2] + k;
|
||||
cellPoints[4] = i*numPoints[1]*numPoints[2] +
|
||||
j*numPoints[2] + k+1;
|
||||
cellPoints[5] = (i+1)*numPoints[1]*numPoints[2] +
|
||||
j*numPoints[2] + k+1;
|
||||
cellPoints[6] = (i+1)*numPoints[1]*numPoints[2] +
|
||||
(j+1)*numPoints[2] + k+1;
|
||||
cellPoints[7] = i*numPoints[1]*numPoints[2] +
|
||||
(j+1)*numPoints[2] + k+1;
|
||||
std::copy(cellPoints, cellPoints+8, std::back_inserter(this->Cells));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t Grid::GetNumberOfPoints()
|
||||
{
|
||||
return this->Points.size()/3;
|
||||
}
|
||||
|
||||
size_t Grid::GetNumberOfCells()
|
||||
{
|
||||
return this->Cells.size()/8;
|
||||
}
|
||||
|
||||
double* Grid::GetPointsArray()
|
||||
{
|
||||
if(this->Points.empty())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return &(this->Points[0]);
|
||||
}
|
||||
|
||||
double* Grid::GetPoint(size_t pointId)
|
||||
{
|
||||
if(pointId >= this->Points.size())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return &(this->Points[pointId*3]);
|
||||
}
|
||||
|
||||
unsigned int* Grid::GetCellPoints(size_t cellId)
|
||||
{
|
||||
if(cellId >= this->Cells.size())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return &(this->Cells[cellId*8]);
|
||||
}
|
||||
|
||||
Attributes::Attributes()
|
||||
{
|
||||
this->GridPtr = NULL;
|
||||
}
|
||||
|
||||
void Attributes::Initialize(Grid* grid)
|
||||
{
|
||||
this->GridPtr = grid;
|
||||
}
|
||||
|
||||
void Attributes::UpdateFields(double time)
|
||||
{
|
||||
size_t numPoints = this->GridPtr->GetNumberOfPoints();
|
||||
this->Velocity.resize(numPoints*3);
|
||||
for(size_t pt=0;pt<numPoints;pt++)
|
||||
{
|
||||
double* coord = this->GridPtr->GetPoint(pt);
|
||||
this->Velocity[pt] = coord[1]*time;
|
||||
//this->Velocity[pt] = time;
|
||||
}
|
||||
std::fill(this->Velocity.begin()+numPoints, this->Velocity.end(), 0.);
|
||||
size_t numCells = this->GridPtr->GetNumberOfCells();
|
||||
this->Pressure.resize(numCells);
|
||||
std::fill(this->Pressure.begin(), this->Pressure.end(), 1.);
|
||||
}
|
||||
|
||||
double* Attributes::GetVelocityArray()
|
||||
{
|
||||
if(this->Velocity.empty())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return &this->Velocity[0];
|
||||
}
|
||||
|
||||
float* Attributes::GetPressureArray()
|
||||
{
|
||||
if(this->Pressure.empty())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return &this->Pressure[0];
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
#ifndef FEDATASTRUCTURES_HEADER
|
||||
#define FEDATASTRUCTURES_HEADER
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
class Grid
|
||||
{
|
||||
public:
|
||||
Grid();
|
||||
void Initialize(const unsigned int numPoints[3], const double spacing[3]);
|
||||
size_t GetNumberOfPoints();
|
||||
size_t GetNumberOfCells();
|
||||
double* GetPointsArray();
|
||||
double* GetPoint(size_t pointId);
|
||||
unsigned int* GetCellPoints(size_t cellId);
|
||||
private:
|
||||
std::vector<double> Points;
|
||||
std::vector<unsigned int> Cells;
|
||||
};
|
||||
|
||||
class Attributes
|
||||
{
|
||||
// A class for generating and storing point and cell fields.
|
||||
// Velocity is stored at the points and pressure is stored
|
||||
// for the cells. The current velocity profile is for a
|
||||
// shearing flow with U(y,t) = y*t, V = 0 and W = 0.
|
||||
// Pressure is constant through the domain.
|
||||
public:
|
||||
Attributes();
|
||||
void Initialize(Grid* grid);
|
||||
void UpdateFields(double time);
|
||||
double* GetVelocityArray();
|
||||
float* GetPressureArray();
|
||||
|
||||
private:
|
||||
std::vector<double> Velocity;
|
||||
std::vector<float> Pressure;
|
||||
Grid* GridPtr;
|
||||
};
|
||||
#endif
|
||||
@ -0,0 +1,81 @@
|
||||
#include "FEDataStructures.h"
|
||||
#include <mpi.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifdef USE_CATALYST
|
||||
#include "FEAdaptor.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <cstring>
|
||||
|
||||
// Example of a C++ adaptor for a simulation code
|
||||
// where the simulation code has a fixed topology
|
||||
// grid. We treat the grid as an unstructured
|
||||
// grid even though in the example provided it
|
||||
// would be best described as a vtkImageData.
|
||||
// Also, the points are stored in an inconsistent
|
||||
// manner with respect to the velocity vector.
|
||||
// This is purposefully done to demonstrate
|
||||
// the different approaches for getting data
|
||||
// into Catalyst. The simulation can be run
|
||||
// from a restarted time step with the
|
||||
// -- restart <time step> command line argument.
|
||||
// All other arguments are considered to be input
|
||||
// script. Note that through configuration
|
||||
// that the driver can be run without linking
|
||||
// to Catalyst.
|
||||
#include <unistd.h>
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
MPI_Init(&argc, &argv);
|
||||
|
||||
Grid grid;
|
||||
unsigned int numPoints[3] = {70, 60, 44};
|
||||
double spacing[3] = {1, 1.1, 1.3};
|
||||
grid.Initialize(numPoints, spacing);
|
||||
Attributes attributes;
|
||||
attributes.Initialize(&grid);
|
||||
|
||||
// we are doing a restarted simulation
|
||||
unsigned int startTimeStep = 0;
|
||||
|
||||
std::vector<std::string> scripts;
|
||||
for(int i=1;i<argc;i++)
|
||||
{
|
||||
if(strcmp(argv[i], "--restart") == 0)
|
||||
{
|
||||
if(i+1 < argc)
|
||||
{
|
||||
startTimeStep = static_cast<unsigned int>(atoi(argv[2]));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
scripts.push_back(argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_CATALYST
|
||||
FEAdaptor::Initialize(scripts);
|
||||
#endif
|
||||
unsigned int numberOfTimeSteps = 50;
|
||||
for(unsigned int timeStep=startTimeStep;timeStep<=startTimeStep+numberOfTimeSteps;timeStep++)
|
||||
{
|
||||
// use a time step length of 0.018
|
||||
double time = timeStep * 0.018;
|
||||
attributes.UpdateFields(time);
|
||||
#ifdef USE_CATALYST
|
||||
FEAdaptor::CoProcess(grid, attributes, time, timeStep, timeStep == numberOfTimeSteps+startTimeStep);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_CATALYST
|
||||
FEAdaptor::Finalize();
|
||||
#endif
|
||||
MPI_Finalize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
# CoProcessing test expects the following arguments to be passed to cmake using
|
||||
# -DFoo=BAR arguments.
|
||||
|
||||
# COPROCESSING_TEST_DRIVER -- path to CxxParticlePathExample
|
||||
# COPROCESSING_TEST_DIR -- path to temporary dir
|
||||
# COPROCESSING_SOURCE_DIR -- path to where the source code with the python scripts are
|
||||
# PVBATCH
|
||||
# MPIEXEC
|
||||
# MPIEXEC_NUMPROC_FLAG
|
||||
# MPIEXEC_NUMPROCS
|
||||
# MPIEXEC_PREFLAGS
|
||||
# VTK_MPI_POSTFLAGS
|
||||
|
||||
# remove result files generated by the test
|
||||
file(REMOVE "${COPROCESSING_TEST_DIR}/particles*vtp" )
|
||||
|
||||
if(NOT EXISTS "${COPROCESSING_TEST_DRIVER}")
|
||||
message(FATAL_ERROR "'${COPROCESSING_TEST_DRIVER}' does not exist")
|
||||
endif()
|
||||
|
||||
message("Executing :
|
||||
${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MPIEXEC_NUMPROCS} ${MPIEXEC_PREFLAGS}
|
||||
\"${COPROCESSING_TEST_DRIVER}\"
|
||||
\"${COPROCESSING_SOURCE_DIR}/SampleScripts/particlepath.py\"")
|
||||
execute_process(COMMAND
|
||||
${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MPIEXEC_NUMPROCS} ${MPIEXEC_PREFLAGS}
|
||||
"${COPROCESSING_TEST_DRIVER}"
|
||||
"${COPROCESSING_SOURCE_DIR}/SampleScripts/particlepath.py"
|
||||
WORKING_DIRECTORY ${COPROCESSING_TEST_DIR}
|
||||
RESULT_VARIABLE rv)
|
||||
|
||||
if(NOT rv EQUAL 0)
|
||||
message(FATAL_ERROR "Test executable return value was ${rv}")
|
||||
endif()
|
||||
|
||||
# below is the restarted "simulation"
|
||||
message("Executing (restart):
|
||||
${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MPIEXEC_NUMPROCS} ${MPIEXEC_PREFLAGS}
|
||||
\"${COPROCESSING_TEST_DRIVER}\" --restart 50
|
||||
\"${COPROCESSING_SOURCE_DIR}/SampleScripts/particlepath.py\"")
|
||||
execute_process(COMMAND
|
||||
${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MPIEXEC_NUMPROCS} ${MPIEXEC_PREFLAGS}
|
||||
"${COPROCESSING_TEST_DRIVER}" --restart 50
|
||||
"${COPROCESSING_SOURCE_DIR}/SampleScripts/particlepath.py"
|
||||
WORKING_DIRECTORY ${COPROCESSING_TEST_DIR}
|
||||
RESULT_VARIABLE rv)
|
||||
|
||||
if(NOT rv EQUAL 0)
|
||||
message(FATAL_ERROR "Test executable (restart) return value was ${rv}")
|
||||
endif()
|
||||
|
||||
message("Executing :
|
||||
${PVBATCH} ${COPROCESSING_SOURCE_DIR}/TestScripts/verifyparticlepath.py ${COPROCESSING_TEST_DIR}")
|
||||
|
||||
execute_process(COMMAND "${PVBATCH}" "${COPROCESSING_SOURCE_DIR}/TestScripts/verifyparticlepath.py" "${COPROCESSING_TEST_DIR}"
|
||||
RESULT_VARIABLE rv
|
||||
WORKING_DIRECTORY ${COPROCESSING_TEST_DIR})
|
||||
|
||||
if(NOT rv EQUAL 0)
|
||||
message(FATAL_ERROR "verifyparticlepath.py failed.")
|
||||
endif()
|
||||
@ -0,0 +1,131 @@
|
||||
from paraview.simple import *
|
||||
from paraview import coprocessing
|
||||
|
||||
outputfrequency = 1
|
||||
reinjectionfrequency = 70
|
||||
|
||||
# ----------------------- CoProcessor definition -----------------------
|
||||
|
||||
def CreateCoProcessor():
|
||||
def _CreatePipeline(coprocessor, datadescription):
|
||||
class Pipeline:
|
||||
# state file generated using paraview version 4.4.0-117-ge0a3d77
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# setup the data processing pipelines
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
#### disable automatic camera reset on 'Show'
|
||||
paraview.simple._DisableFirstRenderCameraReset()
|
||||
|
||||
# create a new 'Line' for seed sources
|
||||
line1 = Line()
|
||||
line1.Point1 = [1., 1., 30.]
|
||||
line1.Point2 = [1., 64., 30.]
|
||||
|
||||
# create a producer from a simulation input
|
||||
fullgrid_99pvtu = coprocessor.CreateProducer(datadescription, 'input')
|
||||
|
||||
# create a new 'ParticlePath'
|
||||
# disable resetting the cache so that the particle path filter works in situ
|
||||
# and only updates from previously computed information.
|
||||
particlePath1 = InSituParticlePath(Input=fullgrid_99pvtu, SeedSource=line1, DisableResetCache=1)
|
||||
particlePath1.SelectInputVectors = ['POINTS', 'velocity']
|
||||
# don't save particle locations from previous time steps. they can take
|
||||
# up a surprising amount of memory for long running simulations.
|
||||
particlePath1.ClearCache = 1
|
||||
|
||||
# if we're starting from a restarted simulation, the following are
|
||||
# used to specify the time step for the restarted simulation and
|
||||
# the input for the previously advected particles to continue
|
||||
# advecting them
|
||||
if datadescription.GetTimeStep() != 0:
|
||||
restartparticles = XMLPartitionedPolydataReader(FileName='particles_50.pvtp')
|
||||
particlePath1.RestartSource = restartparticles
|
||||
particlePath1.FirstTimeStep = datadescription.GetTimeStep()
|
||||
particlePath1.RestartedSimulation = 1
|
||||
|
||||
# create a new 'Parallel PolyData Writer'
|
||||
parallelPolyDataWriter1 = servermanager.writers.XMLPPolyDataWriter(Input=particlePath1)
|
||||
|
||||
# register the writer with coprocessor
|
||||
# and provide it with information such as the filename to use,
|
||||
# how frequently to write the data, etc.
|
||||
coprocessor.RegisterWriter(parallelPolyDataWriter1, filename='particles_%t.pvtp', freq=outputfrequency)
|
||||
|
||||
return Pipeline()
|
||||
|
||||
class CoProcessor(coprocessing.CoProcessor):
|
||||
def CreatePipeline(self, datadescription):
|
||||
self.Pipeline = _CreatePipeline(self, datadescription)
|
||||
|
||||
coprocessor = CoProcessor()
|
||||
# these are the frequencies at which the coprocessor updates. for
|
||||
# particle paths this is done every time step
|
||||
freqs = {'input': [1]}
|
||||
coprocessor.SetUpdateFrequencies(freqs)
|
||||
return coprocessor
|
||||
|
||||
#--------------------------------------------------------------
|
||||
# Global variables that will hold the pipeline for each timestep
|
||||
# Creating the CoProcessor object, doesn't actually create the ParaView pipeline.
|
||||
# It will be automatically setup when coprocessor.UpdateProducers() is called the
|
||||
# first time.
|
||||
coprocessor = CreateCoProcessor()
|
||||
|
||||
#--------------------------------------------------------------
|
||||
# Enable Live-Visualizaton with ParaView
|
||||
coprocessor.EnableLiveVisualization(False, 1)
|
||||
|
||||
# ---------------------- Data Selection method ----------------------
|
||||
|
||||
def RequestDataDescription(datadescription):
|
||||
"Callback to populate the request for current timestep"
|
||||
global coprocessor
|
||||
if datadescription.GetForceOutput() == True:
|
||||
# We are just going to request all fields and meshes from the simulation
|
||||
# code/adaptor.
|
||||
for i in range(datadescription.GetNumberOfInputDescriptions()):
|
||||
datadescription.GetInputDescription(i).AllFieldsOn()
|
||||
datadescription.GetInputDescription(i).GenerateMeshOn()
|
||||
return
|
||||
|
||||
# setup requests for all inputs based on the requirements of the
|
||||
# pipeline.
|
||||
coprocessor.LoadRequestedData(datadescription)
|
||||
|
||||
# ------------------------ Processing method ------------------------
|
||||
|
||||
def DoCoProcessing(datadescription):
|
||||
"Callback to do co-processing for current timestep"
|
||||
global coprocessor
|
||||
|
||||
# Update the coprocessor by providing it the newly generated simulation data.
|
||||
# If the pipeline hasn't been setup yet, this will setup the pipeline.
|
||||
#if not coprocessor.__PipelineCreated:
|
||||
coprocessor.UpdateProducers(datadescription)
|
||||
|
||||
# tell the particle path filter how far to integrate in time (i.e. our current time)
|
||||
coprocessor.Pipeline.particlePath1.TerminationTime = datadescription.GetTime()
|
||||
|
||||
# specify reinjection frequency manually so that reinjection
|
||||
# occurs based on the simulation time step to avoid restart issues since
|
||||
# the particle path filter only knows how many time steps
|
||||
# it has been updated. this is the same when the simulation has not been
|
||||
# restarted.
|
||||
timestep = datadescription.GetTimeStep()
|
||||
if timestep % reinjectionfrequency == 0:
|
||||
coprocessor.Pipeline.particlePath1.ForceReinjectionEveryNSteps = 1
|
||||
else:
|
||||
coprocessor.Pipeline.particlePath1.ForceReinjectionEveryNSteps = timestep+1
|
||||
|
||||
coprocessor.Pipeline.particlePath1.UpdatePipeline()
|
||||
|
||||
# Write output data, if appropriate.
|
||||
coprocessor.WriteData(datadescription);
|
||||
|
||||
# Write image capture (Last arg: rescale lookup table), if appropriate.
|
||||
coprocessor.WriteImages(datadescription, rescale_lookuptable=False)
|
||||
|
||||
# Live Visualization, if enabled.
|
||||
coprocessor.DoLiveVisualization(datadescription, "localhost", 22222)
|
||||
@ -0,0 +1,91 @@
|
||||
import sys
|
||||
|
||||
print 'running the test script with args', sys.argv
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
print 'need to pass in the test directory location'
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# the velocity is [y*t, 0, 0] and the time step length is 0.018
|
||||
# the beginning x-location for the seeds is 1
|
||||
# the y location for the seeds are [1, 11.5, 22, 32.5, 43, 53.5, 64]
|
||||
# the z location for the seeds is 30
|
||||
# the analytical locations of the initially injected seeds are 1+y*time*time/2
|
||||
# the seeds are reinjected at time step 70 (time 1.26) and their
|
||||
# analytical locations are 1+y*(time*time-1.26*1.26)/2
|
||||
|
||||
# in parallel when seeds are migrated to different processes there
|
||||
# is a slight loss of accuracy due to using a first order time
|
||||
# integration method instead of vtkRungeKutta4.cxx.
|
||||
|
||||
from paraview.simple import *
|
||||
r = XMLPartitionedPolydataReader(FileName=sys.argv[1]+'/particles_40.pvtp')
|
||||
r.UpdatePipeline()
|
||||
bounds = r.GetDataInformation().DataInformation.GetBounds()
|
||||
if bounds[0] < 1.25 or bounds[0] > 1.27 or \
|
||||
bounds[1] < 17.5 or bounds[1] > 17.7 or \
|
||||
bounds[2] < .9 or bounds[2] > 1.1 or \
|
||||
bounds[3] < 63.9 or bounds[3] > 64.1 or \
|
||||
bounds[4] < 29.9 or bounds[4] > 30.1 or \
|
||||
bounds[5] < 29.9 or bounds[5] > 30.1:
|
||||
print 'Time step 40: wrong particle bounds', bounds
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
g = Glyph()
|
||||
g.GlyphMode = 'All Points'
|
||||
g.GlyphType = '2D Glyph'
|
||||
g.GlyphType.GlyphType = 'Vertex'
|
||||
|
||||
t = Threshold()
|
||||
t.Scalars = ['POINTS', 'ParticleAge']
|
||||
t.ThresholdRange = [0.71, 0.73]
|
||||
t.UpdatePipeline()
|
||||
|
||||
grid = servermanager.Fetch(t)
|
||||
if grid.GetNumberOfPoints() != 7:
|
||||
print 'Time step 40: wrong number of points', grid.GetNumberOfPoints()
|
||||
sys.exit(1)
|
||||
|
||||
r.FileName = sys.argv[1]+'/particles_80.pvtp'
|
||||
|
||||
# threshold to get the seeds that were originally injected only
|
||||
t.ThresholdRange = [1.43, 1.45]
|
||||
t.UpdatePipeline()
|
||||
bounds = t.GetDataInformation().DataInformation.GetBounds()
|
||||
if bounds[0] < 2. or bounds[0] > 2.1 or \
|
||||
bounds[1] < 67.3 or bounds[1] > 67.4 or \
|
||||
bounds[2] < .9 or bounds[2] > 1.1 or \
|
||||
bounds[3] < 63.9 or bounds[3] > 64.1 or \
|
||||
bounds[4] < 29.9 or bounds[4] > 30.1 or \
|
||||
bounds[5] < 29.9 or bounds[5] > 30.1:
|
||||
print 'Time step 80: wrong particle bounds for initial injected particles', bounds
|
||||
sys.exit(1)
|
||||
|
||||
grid = servermanager.Fetch(t)
|
||||
if grid.GetNumberOfPoints() != 7:
|
||||
print 'Time step 80: wrong number of points for initial injected particles', grid.GetNumberOfPoints()
|
||||
sys.exit(1)
|
||||
|
||||
# threshold to get the seeds that were injected at time step 70
|
||||
t.Scalars = ['POINTS', 'InjectionStepId']
|
||||
t.ThresholdRange = [69, 71]
|
||||
t.UpdatePipeline()
|
||||
|
||||
bounds = t.GetDataInformation().DataInformation.GetBounds()
|
||||
if bounds[0] < 1.23 or bounds[0] > 1.25 or \
|
||||
bounds[1] < 16.5 or bounds[1] > 16.7 or \
|
||||
bounds[2] < .9 or bounds[2] > 1.1 or \
|
||||
bounds[3] < 63.9 or bounds[3] > 64.1 or \
|
||||
bounds[4] < 29.9 or bounds[4] > 30.1 or \
|
||||
bounds[5] < 29.9 or bounds[5] > 30.1:
|
||||
print 'Time step 80: wrong particle bounds for reinjected particles', bounds
|
||||
sys.exit(1)
|
||||
|
||||
grid = servermanager.Fetch(t)
|
||||
if grid.GetNumberOfPoints() != 7:
|
||||
print 'Time step 80: wrong number of points for reinjected particles', grid.GetNumberOfPoints()
|
||||
sys.exit(1)
|
||||
|
||||
print 'test passed'
|
||||
Reference in New Issue
Block a user