# Generate3DAMRDataSetWithPulse

VTKExamples/Cxx/CompositeData/Generate3DAMRDataSetWithPulse

### Description

This utility code generates a simple 3D AMR dataset with a Gaussian pulse at the center. The resulting AMR dataset is written using the vtkXMLHierarchicalBoxDataSetWriter.

Note

The original source code for this example is here.

### Code

Generate3DAMRDataSetWithPulse.cxx

    // .NAME Generate3DAMRDataSetWithPulse.cxx -- Generated sample 3D AMR dataset
    //
    // .SECTION Description
    //  This utility code generates a simple 3D AMR dataset with a gaussian
    //  pulse at the center. The resulting AMR dataset is written using the
    //  vtkXMLHierarchicalBoxDataSetWriter.

    #include <cmath>
    #include <iostream>
    #include <sstream>

    #include <vtkAMRBox.h>
    #include <vtkAMRUtilities.h>
    #include <vtkCell.h>
    #include <vtkCellData.h>
    #include <vtkCompositeDataWriter.h>
    #include <vtkDataArray.h>
    #include <vtkDoubleArray.h>
    #include <vtkHierarchicalBoxDataSet.h>
    #include <vtkMultiBlockDataSet.h>
    #include <vtkOverlappingAMR.h>
    #include <vtkPointData.h>
    #include <vtkPoints.h>
    #include <vtkUniformGrid.h>
    #include <vtkXMLHierarchicalBoxDataReader.h>
    #include <vtkXMLImageDataWriter.h>
    #include <vtkXMLMultiBlockDataWriter.h>

    namespace
    {
      namespace AMRCommon
      {
        void WriteUniformGrid(vtkUniformGrid* g, const std::string& prefix);
        void WriteAMRData(vtkOverlappingAMR* amrData, const std::string& prefix);
        vtkHierarchicalBoxDataSet* ReadAMRData(const std::string& file);
        void WriteMultiBlockData(vtkMultiBlockDataSet* mbds, const std::string& prefix);
        vtkUniformGrid* GetGrid(double* origin, double* h, int* ndim);
        void ComputeCellCenter(vtkUniformGrid* grid, const int cellIdx, double c[3]);
      }
    }
    namespace
    {
      static struct PulseAttributes
      {
        double origin[3]; // xyz for the center of the pulse
        double width[3]; // the width of the pulse
        double amplitude; // the amplitude of the pulse
      } Pulse;

      //
      // Function prototype declarations
      //

      // Description:
      // Sets the pulse attributes
      void SetPulse();

      // Description:
      // Constructs the vtkHierarchicalBoxDataSet.
      vtkOverlappingAMR* GetAMRDataSet();

      // Description:
      // Attaches the pulse to the given grid.
      void AttachPulseToGrid(vtkUniformGrid* grid);
    }

    //
    // Program main
    //
    int main(int, char*[])
    {
      // STEP 0: Initialize gaussian pulse parameters
      SetPulse();

      // STEP 1: Get the AMR dataset
      vtkSmartPointer<vtkOverlappingAMR> amrDataSet;
      amrDataSet.TakeReference(GetAMRDataSet());

      AMRCommon::WriteAMRData(amrDataSet, "Gaussian3D");
      return 0;
    }
    namespace
    {
      //=============================================================================
      //                    Function Prototype Implementation
      //=============================================================================

      void SetPulse()
      {
        Pulse.origin[0] = Pulse.origin[1] = Pulse.origin[2] = -1.0;
        Pulse.width[0] = Pulse.width[1] = Pulse.width[2] = 6.0;
        Pulse.amplitude = 0.0001;
      }

      //------------------------------------------------------------------------------
      void AttachPulseToGrid(vtkUniformGrid* grid)
      {
        vtkSmartPointer<vtkDoubleArray> xyz =
          vtkSmartPointer<vtkDoubleArray>::New();
        xyz->SetName("GaussianPulse");
        xyz->SetNumberOfComponents(1);
        xyz->SetNumberOfTuples(grid->GetNumberOfCells());

        for (int cellIdx = 0; cellIdx < grid->GetNumberOfCells(); ++cellIdx)
        {
          double center[3];
          AMRCommon::ComputeCellCenter(grid, cellIdx, center);

          double r = 0.0;
          for (int i = 0; i < 3; ++i)
          {
            double dx = center[i] - Pulse.origin[i];
            r += (dx * dx) / (Pulse.width[i] * Pulse.width[i]);
          }
          double f = Pulse.amplitude * std::exp(-r);

          xyz->SetTuple1(cellIdx, f);
        } // END for all cells

        grid->GetCellData()->AddArray(xyz);
      }
      //------------------------------------------------------------------------------
      vtkOverlappingAMR* GetAMRDataSet()
      {
        vtkOverlappingAMR* data = vtkOverlappingAMR::New();
        int blocksPerLevel[2] = { 1, 3 };
        double globalOrigin[3] = { -2.0, -2.0, -2.0 };
        data->Initialize(2, blocksPerLevel);
        data->SetOrigin(globalOrigin);
        data->SetGridDescription(VTK_XYZ_GRID);

        double origin[3];
        double h[3];
        int ndim[3];

        // Root Block -- Block 0
        ndim[0] = 6;
        ndim[1] = ndim[2] = 5;
        h[0] = h[1] = h[2] = 1.0;
        origin[0] = origin[1] = origin[2] = -2.0;
        int blockId = 0;
        int level = 0;
        vtkSmartPointer<vtkUniformGrid> root;
        root.TakeReference(
          AMRCommon::GetGrid(origin, h, ndim));
        vtkAMRBox box(origin, ndim, h, data->GetOrigin(), data->GetGridDescription());
        AttachPulseToGrid(root);
        data->SetSpacing(level, h);
        data->SetAMRBox(level, blockId, box);
        data->SetDataSet(level, blockId, root);

        // Block 1
        ndim[0] = 3;
        ndim[1] = ndim[2] = 5;
        h[0] = h[1] = h[2] = 0.5;
        origin[0] = origin[1] = origin[2] = -2.0;
        blockId = 0;
        level = 1;
        vtkSmartPointer<vtkUniformGrid> grid1;
        grid1.TakeReference(
          AMRCommon::GetGrid(origin, h, ndim));
        vtkAMRBox box1(origin, ndim, h, data->GetOrigin(),
          data->GetGridDescription());
        AttachPulseToGrid(grid1);
        data->SetSpacing(level, h);
        data->SetAMRBox(level, blockId, box1);
        data->SetDataSet(level, blockId, grid1);

        // Block 2
        ndim[0] = 3;
        ndim[1] = ndim[2] = 5;
        h[0] = h[1] = h[2] = 0.5;
        origin[0] = 0.0;
        origin[1] = origin[2] = -1.0;
        blockId = 1;
        level = 1;
        vtkSmartPointer<vtkUniformGrid> grid2;
        grid2.TakeReference(
          AMRCommon::GetGrid(origin, h, ndim));
        vtkAMRBox box2(origin, ndim, h, data->GetOrigin(),
                       data->GetGridDescription());
        AttachPulseToGrid(grid2);
        data->SetSpacing(level, h);
        data->SetAMRBox(level, blockId, box2);
        data->SetDataSet(level, blockId, grid2);

        // Block 3
        ndim[0] = 3;
        ndim[1] = ndim[2] = 7;
        h[0] = h[1] = h[2] = 0.5;
        origin[0] = 2.0;
        origin[1] = origin[2] = -1.0;
        blockId = 2;
        level = 1;
        vtkSmartPointer<vtkUniformGrid> grid3;
        grid3.TakeReference(AMRCommon::GetGrid(origin, h, ndim));
        vtkAMRBox box3(origin, ndim, h, data->GetOrigin(),
          data->GetGridDescription());
        AttachPulseToGrid(grid3);
        data->SetSpacing(level, h);
        data->SetAMRBox(level, blockId, box3);
        data->SetDataSet(level, blockId, grid3);

        vtkAMRUtilities::BlankCells(data);
        return (data);
      }
    }
    namespace
    {
      namespace AMRCommon
      {

        //------------------------------------------------------------------------------
        // Description:
        // Writes a uniform grid as a structure grid
        void WriteUniformGrid(vtkUniformGrid* g, const std::string& prefix)
        {
          vtkSmartPointer<vtkXMLImageDataWriter> imgWriter =
            vtkSmartPointer<vtkXMLImageDataWriter>::New();

          std::ostringstream oss;
          oss << prefix << "." << imgWriter->GetDefaultFileExtension();
          imgWriter->SetFileName(oss.str().c_str());
          imgWriter->SetInputData(g);
          imgWriter->Write();
        }

        //------------------------------------------------------------------------------
        // Description:
        // Writes the given AMR dataset to a *.vth file with the given prefix.
        void WriteAMRData(vtkOverlappingAMR* amrData, const std::string& prefix)
        {
          vtkSmartPointer<vtkCompositeDataWriter> writer =
            vtkSmartPointer<vtkCompositeDataWriter>::New();

          std::ostringstream oss;
          oss << prefix << ".vthb";
          writer->SetFileName(oss.str().c_str());
          writer->SetInputData(amrData);
          writer->Write();
        }

        //------------------------------------------------------------------------------
        // Description:
        // Reads AMR data to the given data-structure from the prescribed file.
        vtkHierarchicalBoxDataSet* ReadAMRData(const std::string& file)
        {
          vtkXMLHierarchicalBoxDataReader* myAMRReader =
            vtkXMLHierarchicalBoxDataReader::New();

          std::ostringstream oss;
          oss.str("");
          oss.clear();
          oss << file << ".vthb";

          std::cout << "Reading AMR Data from: " << oss.str() << std::endl;
          std::cout.flush();

          myAMRReader->SetFileName(oss.str().c_str());
          myAMRReader->Update();

          vtkHierarchicalBoxDataSet* amrData =
            dynamic_cast<vtkHierarchicalBoxDataSet*>(myAMRReader->GetOutput());
          return (amrData);
        }

        //------------------------------------------------------------------------------
        // Description:
        // Writes the given multi-block data to an XML file with the prescribed prefix
        void WriteMultiBlockData(vtkMultiBlockDataSet* mbds, const std::string& prefix)
        {
          // Sanity check
          vtkSmartPointer<vtkXMLMultiBlockDataWriter> writer =
            vtkSmartPointer<vtkXMLMultiBlockDataWriter>::New();

          std::ostringstream oss;
          oss.str("");
          oss.clear();
          oss << prefix << "." << writer->GetDefaultFileExtension();
          writer->SetFileName(oss.str().c_str());
          writer->SetInputData(mbds);
          writer->Write();
        }

        //------------------------------------------------------------------------------
        // Constructs a uniform grid instance given the prescribed
        // origin, grid spacing and dimensions.
        vtkUniformGrid* GetGrid(double* origin, double* h, int* ndim)
        {
          vtkUniformGrid* grd = vtkUniformGrid::New();
          grd->Initialize();
          grd->SetOrigin(origin);
          grd->SetSpacing(h);
          grd->SetDimensions(ndim);
          return grd;
        }

        //------------------------------------------------------------------------------
        // Computes the cell center for the cell corresponding to cellIdx w.r.t.
        // the given grid. The cell center is stored in the supplied buffer c.
        void ComputeCellCenter(vtkUniformGrid* grid, const int cellIdx, double c[3])
        {
          vtkCell* myCell = grid->GetCell(cellIdx);

          double pCenter[3];
          double* weights = new double[myCell->GetNumberOfPoints()];
          int subId = myCell->GetParametricCenter(pCenter);
          myCell->EvaluateLocation(subId, pCenter, c, weights);
          delete[] weights;
        }
      }
    }

### CMakeLists.txt

    cmake_minimum_required(VERSION 3.3 FATAL_ERROR)

    project(Generate3DAMRDataSetWithPulse)

    find_package(VTK COMPONENTS
      vtkCommonCore
      vtkCommonDataModel
      vtkIOLegacy
      vtkIOXML QUIET)
    if (NOT VTK_FOUND)
      message("Skipping Generate3DAMRDataSetWithPulse: ${VTK_NOT_FOUND_MESSAGE}")
      return ()
    endif()
    message (STATUS "VTK_VERSION: ${VTK_VERSION}")
    if (VTK_VERSION VERSION_LESS "8.90.0")
      # old system
      include(${VTK_USE_FILE})
      add_executable(Generate3DAMRDataSetWithPulse MACOSX_BUNDLE Generate3DAMRDataSetWithPulse.cxx )
      target_link_libraries(Generate3DAMRDataSetWithPulse PRIVATE ${VTK_LIBRARIES})
    else ()
      # include all components
      add_executable(Generate3DAMRDataSetWithPulse MACOSX_BUNDLE Generate3DAMRDataSetWithPulse.cxx )
      target_link_libraries(Generate3DAMRDataSetWithPulse PRIVATE ${VTK_LIBRARIES})
      # vtk_module_autoinit is needed
      vtk_module_autoinit(
        TARGETS Generate3DAMRDataSetWithPulse
        MODULES ${VTK_LIBRARIES}
        )
    endif ()

### Download and Build Generate3DAMRDataSetWithPulse

Click here to download Generate3DAMRDataSetWithPulse and its CMakeLists.txt file. Once the tarball Generate3DAMRDataSetWithPulse.tar has been downloaded and extracted,

    cd Generate3DAMRDataSetWithPulse/build

If VTK is installed:

    cmake ..

If VTK is not installed but compiled on your system, you will need to specify the path to your VTK build:

    cmake -DVTK_DIR:PATH=/home/me/vtk_build ..

Build the project:

    make

and run it:

    ./Generate3DAMRDataSetWithPulse

WINDOWS USERS

Be sure to add the VTK bin directory to your path. This will resolve the VTK dll's at run time.