From e95f7a603fc63713dc32145592b9720d927c507b Mon Sep 17 00:00:00 2001
From: Petr Strakos <petrstrakos@eduroam-227-74.vsb.cz>
Date: Wed, 9 Jan 2019 14:54:11 +0100
Subject: [PATCH] adding sources for a simple simulation code, setting user

---
 docs.it4i/software/viz/insitu/CMakeLists.txt  |  41 +++++
 docs.it4i/software/viz/insitu/FEAdaptor.cxx   | 162 ++++++++++++++++++
 docs.it4i/software/viz/insitu/FEAdaptor.h     |  17 ++
 .../software/viz/insitu/FEDataStructures.cxx  | 155 +++++++++++++++++
 .../software/viz/insitu/FEDataStructures.h    |  42 +++++
 docs.it4i/software/viz/insitu/FEDriver.cxx    |  65 +++++++
 .../software/viz/insitu/feslicescript.py      |  93 ++++++++++
 docs.it4i/software/viz/insitu/insitu.tar.gz   | Bin 0 -> 5687 bytes
 8 files changed, 575 insertions(+)
 create mode 100644 docs.it4i/software/viz/insitu/CMakeLists.txt
 create mode 100644 docs.it4i/software/viz/insitu/FEAdaptor.cxx
 create mode 100644 docs.it4i/software/viz/insitu/FEAdaptor.h
 create mode 100644 docs.it4i/software/viz/insitu/FEDataStructures.cxx
 create mode 100644 docs.it4i/software/viz/insitu/FEDataStructures.h
 create mode 100644 docs.it4i/software/viz/insitu/FEDriver.cxx
 create mode 100644 docs.it4i/software/viz/insitu/feslicescript.py
 create mode 100644 docs.it4i/software/viz/insitu/insitu.tar.gz

diff --git a/docs.it4i/software/viz/insitu/CMakeLists.txt b/docs.it4i/software/viz/insitu/CMakeLists.txt
new file mode 100644
index 000000000..c1f7b97df
--- /dev/null
+++ b/docs.it4i/software/viz/insitu/CMakeLists.txt
@@ -0,0 +1,41 @@
+cmake_minimum_required(VERSION 3.3)
+project(CatalystCxxFullExample)
+
+include_directories(/apps/all/ParaView/5.6.0-intel-2017a-mpi/include/paraview-5.6/)
+link_directories(/apps/all/ParaView/5.6.0-intel-2017a-mpi/lib/)
+
+set(USE_CATALYST ON CACHE BOOL "Link the simulator with Catalyst")
+if(USE_CATALYST)
+  find_package(ParaView 4.1 REQUIRED COMPONENTS vtkPVPythonCatalyst)
+  include("${PARAVIEW_USE_FILE}")
+  set(Adaptor_SRCS
+    FEAdaptor.cxx
+    )
+  add_library(CxxFullExampleAdaptor ${Adaptor_SRCS})
+  target_link_libraries(CxxFullExampleAdaptor 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(CxxFullExample FEDriver.cxx FEDataStructures.cxx)
+if(USE_CATALYST)
+  target_link_libraries(CxxFullExample LINK_PRIVATE CxxFullExampleAdaptor)
+  include(vtkModuleMacros)
+  include(vtkMPI)
+  vtk_mpi_link(CxxFullExample)
+else()
+  target_link_libraries(CxxFullExample LINK_PRIVATE ${MPI_LIBRARIES})
+endif()
+
+option(BUILD_TESTING "Build Testing" OFF)
+# Setup testing.
+if (BUILD_TESTING)
+  include(CTest)
+  add_test(NAME CxxFullExampleTest COMMAND CxxFullExample ${CMAKE_CURRENT_SOURCE_DIR}/SampleScripts/feslicescript.py)
+  set_tests_properties(CxxFullExampleTest PROPERTIES LABELS "PARAVIEW;CATALYST")
+endif()
diff --git a/docs.it4i/software/viz/insitu/FEAdaptor.cxx b/docs.it4i/software/viz/insitu/FEAdaptor.cxx
new file mode 100644
index 000000000..6409f18ff
--- /dev/null
+++ b/docs.it4i/software/viz/insitu/FEAdaptor.cxx
@@ -0,0 +1,162 @@
+#include "FEAdaptor.h"
+#include "FEDataStructures.h"
+#include <iostream>
+
+#include <vtkCPDataDescription.h>
+#include <vtkCPInputDataDescription.h>
+#include <vtkCPProcessor.h>
+#include <vtkCPPythonScriptPipeline.h>
+#include <vtkCellData.h>
+#include <vtkCellType.h>
+#include <vtkDoubleArray.h>
+#include <vtkFloatArray.h>
+#include <vtkNew.h>
+#include <vtkPointData.h>
+#include <vtkPoints.h>
+#include <vtkUnstructuredGrid.h>
+
+namespace
+{
+vtkCPProcessor* Processor = NULL;
+vtkUnstructuredGrid* VTKGrid;
+
+void BuildVTKGrid(Grid& grid)
+{
+  // 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, vtkCPInputDataDescription* idd)
+{
+  if (idd->IsFieldNeeded("velocity", vtkDataObject::POINT) == true)
+  {
+    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());
+    }
+    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->SetTypedTuple(i, values);
+    }
+  }
+  if (idd->IsFieldNeeded("pressure", vtkDataObject::CELL) == true)
+  {
+    if (VTKGrid->GetCellData()->GetNumberOfArrays() == 0)
+    {
+      // pressure array
+      vtkNew<vtkFloatArray> pressure;
+      pressure->SetName("pressure");
+      pressure->SetNumberOfComponents(1);
+      VTKGrid->GetCellData()->AddArray(pressure.GetPointer());
+    }
+    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, vtkCPInputDataDescription* idd)
+{
+  if (VTKGrid == NULL)
+  {
+    // The grid structure isn't changing so we only build it
+    // the first time it's needed. If we needed the memory
+    // we could delete it and rebuild as necessary.
+    VTKGrid = vtkUnstructuredGrid::New();
+    BuildVTKGrid(grid);
+  }
+  UpdateVTKAttributes(grid, attributes, idd);
+}
+}
+
+namespace FEAdaptor
+{
+
+void Initialize(int numScripts, char* scripts[])
+{
+  if (Processor == NULL)
+  {
+    Processor = vtkCPProcessor::New();
+    Processor->Initialize();
+  }
+  else
+  {
+    Processor->RemoveAllPipelines();
+  }
+  for (int i = 0; i < numScripts; i++)
+  {
+    vtkNew<vtkCPPythonScriptPipeline> pipeline;
+    pipeline->Initialize(scripts[i]);
+    Processor->AddPipeline(pipeline.GetPointer());
+  }
+}
+
+void Finalize()
+{
+  if (Processor)
+  {
+    Processor->Delete();
+    Processor = NULL;
+  }
+  if (VTKGrid)
+  {
+    VTKGrid->Delete();
+    VTKGrid = NULL;
+  }
+}
+
+void CoProcess(
+  Grid& grid, Attributes& attributes, double time, unsigned int timeStep, bool lastTimeStep)
+{
+  vtkNew<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)
+  {
+    vtkCPInputDataDescription* idd = dataDescription->GetInputDescriptionByName("input");
+    BuildVTKDataStructures(grid, attributes, idd);
+    idd->SetGrid(VTKGrid);
+    Processor->CoProcess(dataDescription.GetPointer());
+  }
+}
+} // end of Catalyst namespace
diff --git a/docs.it4i/software/viz/insitu/FEAdaptor.h b/docs.it4i/software/viz/insitu/FEAdaptor.h
new file mode 100644
index 000000000..9bc277048
--- /dev/null
+++ b/docs.it4i/software/viz/insitu/FEAdaptor.h
@@ -0,0 +1,17 @@
+#ifndef FEADAPTOR_HEADER
+#define FEADAPTOR_HEADER
+
+class Attributes;
+class Grid;
+
+namespace FEAdaptor
+{
+void Initialize(int numScripts, char* scripts[]);
+
+void Finalize();
+
+void CoProcess(
+  Grid& grid, Attributes& attributes, double time, unsigned int timeStep, bool lastTimeStep);
+}
+
+#endif
diff --git a/docs.it4i/software/viz/insitu/FEDataStructures.cxx b/docs.it4i/software/viz/insitu/FEDataStructures.cxx
new file mode 100644
index 000000000..858e450aa
--- /dev/null
+++ b/docs.it4i/software/viz/insitu/FEDataStructures.cxx
@@ -0,0 +1,155 @@
+#include "FEDataStructures.h"
+
+#include <iostream>
+#include <mpi.h>
+
+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);
+  
+  // provide different update setting for different parallel process
+  int mpiSize = 1;
+  int mpiRank = 0;
+  MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
+  MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
+  double setting = 1.0 + (double) mpiRank / (double) mpiSize;
+  
+  for (size_t pt = 0; pt < numPoints; pt++)
+  {
+    double* coord = this->GridPtr->GetPoint(pt);
+    this->Velocity[pt] = coord[1] * time * setting;
+  }
+  std::fill(this->Velocity.begin() + numPoints, this->Velocity.end(), 0.0);
+
+  size_t numCells = this->GridPtr->GetNumberOfCells();
+  this->Pressure.resize(numCells);
+  std::fill(this->Pressure.begin(), this->Pressure.end(), setting);
+}
+
+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];
+}
diff --git a/docs.it4i/software/viz/insitu/FEDataStructures.h b/docs.it4i/software/viz/insitu/FEDataStructures.h
new file mode 100644
index 000000000..b9d39db96
--- /dev/null
+++ b/docs.it4i/software/viz/insitu/FEDataStructures.h
@@ -0,0 +1,42 @@
+#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
diff --git a/docs.it4i/software/viz/insitu/FEDriver.cxx b/docs.it4i/software/viz/insitu/FEDriver.cxx
new file mode 100644
index 000000000..9c7d9ec4e
--- /dev/null
+++ b/docs.it4i/software/viz/insitu/FEDriver.cxx
@@ -0,0 +1,65 @@
+#include "FEDataStructures.h"
+#include <mpi.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <iostream>
+#include <stdlib.h>
+
+#ifdef USE_CATALYST
+#include "FEAdaptor.h"
+#endif
+
+// Example of a C++ adaptor for a simulation code
+
+int main(int argc, char** argv)
+{
+  // Check the input arguments for area size
+  if (argc < 4) {
+	printf("Not all arguments for grid definition supplied\n");
+	return 0;
+  }
+
+  unsigned int pointsX = abs(std::stoi(argv[1])); 
+  unsigned int pointsY = abs(std::stoi(argv[2]));
+  unsigned int pointsZ = abs(std::stoi(argv[3]));
+  
+  //MPI_Init(&argc, &argv);
+  MPI_Init(NULL, NULL);
+  Grid grid;
+
+  unsigned int numPoints[3] = { pointsX, pointsY, pointsZ };
+  double spacing[3] = { 1, 1.1, 1.3 };
+  grid.Initialize(numPoints, spacing);
+  Attributes attributes;
+  attributes.Initialize(&grid);
+
+#ifdef USE_CATALYST
+  // The first argument is the program name
+  FEAdaptor::Initialize(argc - 4, &argv[4]);
+#endif
+  unsigned int numberOfTimeSteps = 1000;
+  for (unsigned int timeStep = 0; timeStep < numberOfTimeSteps; timeStep++)
+  {
+    // use a time step length of 0.1
+    double time = timeStep * 0.1;
+    attributes.UpdateFields(time);
+#ifdef USE_CATALYST
+    FEAdaptor::CoProcess(grid, attributes, time, timeStep, timeStep == numberOfTimeSteps - 1);
+#endif
+    
+    // Get the name of the processor
+    char processor_name[MPI_MAX_PROCESSOR_NAME];
+    int name_len;
+    MPI_Get_processor_name(processor_name, &name_len);
+
+    printf("This is processor %s, time step: %0.3f\n", processor_name, time);
+    usleep(500000);
+  }
+
+#ifdef USE_CATALYST
+  FEAdaptor::Finalize();
+#endif
+  MPI_Finalize();
+
+  return 0;
+}
diff --git a/docs.it4i/software/viz/insitu/feslicescript.py b/docs.it4i/software/viz/insitu/feslicescript.py
new file mode 100644
index 000000000..21e9d7522
--- /dev/null
+++ b/docs.it4i/software/viz/insitu/feslicescript.py
@@ -0,0 +1,93 @@
+from paraview.simple import *
+from paraview import coprocessing
+
+#--------------------------------------------------------------
+# Code generated from cpstate.py to create the CoProcessor.
+
+
+# ----------------------- CoProcessor definition -----------------------
+
+def CreateCoProcessor():
+  def _CreatePipeline(coprocessor, datadescription):
+    class Pipeline:
+      filename_3_pvtu = coprocessor.CreateProducer( datadescription, "input" )
+
+      Slice1 = Slice( guiName="Slice1", Crinkleslice=0, SliceOffsetValues=[0.0], Triangulatetheslice=1, SliceType="Plane" )
+      Slice1.SliceType.Offset = 0.0
+      Slice1.SliceType.Origin = [34.5, 32.45, 27.95]
+      Slice1.SliceType.Normal = [1.0, 0.0, 0.0]
+
+      # create a new 'Parallel PolyData Writer'
+      parallelPolyDataWriter1 = servermanager.writers.XMLPPolyDataWriter(Input=Slice1)
+
+      # 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='slice_%t.pvtp', freq=10)
+
+      # create a new 'Parallel UnstructuredGrid Writer'
+      unstructuredGridWriter1 = servermanager.writers.XMLPUnstructuredGridWriter(Input=filename_3_pvtu)
+
+      # 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(unstructuredGridWriter1, filename='fullgrid_%t.pvtu', freq=100)
+
+    return Pipeline()
+
+  class CoProcessor(coprocessing.CoProcessor):
+    def CreatePipeline(self, datadescription):
+      self.Pipeline = _CreatePipeline(self, datadescription)
+
+  coprocessor = CoProcessor()
+  freqs = {'input': [10, 100]}
+  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)
+
+
+# ---------------------- 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.
+    coprocessor.UpdateProducers(datadescription)
+
+    # 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)
diff --git a/docs.it4i/software/viz/insitu/insitu.tar.gz b/docs.it4i/software/viz/insitu/insitu.tar.gz
new file mode 100644
index 0000000000000000000000000000000000000000..d207465c54760da5dc15d3fae7c05591f7bf5547
GIT binary patch
literal 5687
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

literal 0
HcmV?d00001

-- 
GitLab