254 lines
8.3 KiB
C++
254 lines
8.3 KiB
C++
//============================================================================
|
|
// Copyright (c) Kitware, Inc.
|
|
// All rights reserved.
|
|
// See LICENSE.txt for details.
|
|
//
|
|
// This software is distributed WITHOUT ANY WARRANTY; without even
|
|
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
// PURPOSE. See the above copyright notice for more information.
|
|
//============================================================================
|
|
|
|
#ifndef vtk_m_worklet_particleadvection_GridEvaluators_h
|
|
#define vtk_m_worklet_particleadvection_GridEvaluators_h
|
|
|
|
#include <vtkm/Bitset.h>
|
|
#include <vtkm/CellClassification.h>
|
|
#include <vtkm/Types.h>
|
|
#include <vtkm/VectorAnalysis.h>
|
|
#include <vtkm/cont/ArrayHandle.h>
|
|
#include <vtkm/cont/CellLocatorGeneral.h>
|
|
#include <vtkm/cont/CellLocatorRectilinearGrid.h>
|
|
#include <vtkm/cont/CellLocatorTwoLevel.h>
|
|
#include <vtkm/cont/CellLocatorUniformGrid.h>
|
|
#include <vtkm/cont/CellSetStructured.h>
|
|
#include <vtkm/cont/DataSet.h>
|
|
|
|
#include <vtkm/worklet/particleadvection/CellInterpolationHelper.h>
|
|
#include <vtkm/worklet/particleadvection/Field.h>
|
|
#include <vtkm/worklet/particleadvection/GridEvaluatorStatus.h>
|
|
#include <vtkm/worklet/particleadvection/IntegratorBase.h>
|
|
|
|
namespace vtkm
|
|
{
|
|
namespace worklet
|
|
{
|
|
namespace particleadvection
|
|
{
|
|
|
|
template <typename FieldType>
|
|
class ExecutionGridEvaluator
|
|
{
|
|
using GhostCellArrayType = vtkm::cont::ArrayHandle<vtkm::UInt8>;
|
|
|
|
public:
|
|
VTKM_CONT
|
|
ExecutionGridEvaluator() = default;
|
|
|
|
VTKM_CONT
|
|
ExecutionGridEvaluator(const vtkm::cont::CellLocatorGeneral& locator,
|
|
std::shared_ptr<vtkm::cont::CellInterpolationHelper> interpolationHelper,
|
|
const vtkm::Bounds& bounds,
|
|
const FieldType& field,
|
|
const GhostCellArrayType& ghostCells,
|
|
vtkm::cont::DeviceAdapterId device,
|
|
vtkm::cont::Token& token)
|
|
: Bounds(bounds)
|
|
, Field(field.PrepareForExecution(device, token))
|
|
, GhostCells(ghostCells.PrepareForInput(device, token))
|
|
, HaveGhostCells(ghostCells.GetNumberOfValues() > 0)
|
|
, InterpolationHelper(interpolationHelper->PrepareForExecution(device, token))
|
|
, Locator(locator.PrepareForExecution(device, token))
|
|
{
|
|
}
|
|
|
|
template <typename Point>
|
|
VTKM_EXEC bool IsWithinSpatialBoundary(const Point point) const
|
|
{
|
|
vtkm::Id cellId;
|
|
Point parametric;
|
|
|
|
this->Locator.FindCell(point, cellId, parametric);
|
|
|
|
if (cellId == -1)
|
|
return false;
|
|
else
|
|
return !this->InGhostCell(cellId);
|
|
}
|
|
|
|
VTKM_EXEC
|
|
bool IsWithinTemporalBoundary(const vtkm::FloatDefault& vtkmNotUsed(time)) const { return true; }
|
|
|
|
VTKM_EXEC
|
|
vtkm::Bounds GetSpatialBoundary() const { return this->Bounds; }
|
|
|
|
VTKM_EXEC_CONT
|
|
vtkm::FloatDefault GetTemporalBoundary(vtkm::Id direction) const
|
|
{
|
|
// Return the time of the newest time slice
|
|
return direction > 0 ? vtkm::Infinity<vtkm::FloatDefault>()
|
|
: vtkm::NegativeInfinity<vtkm::FloatDefault>();
|
|
}
|
|
|
|
template <typename Point>
|
|
VTKM_EXEC GridEvaluatorStatus Evaluate(const Point& point,
|
|
const vtkm::FloatDefault& time,
|
|
vtkm::VecVariable<Point, 2>& out) const
|
|
{
|
|
vtkm::Id cellId = -1;
|
|
Point parametric;
|
|
GridEvaluatorStatus status;
|
|
|
|
status.SetOk();
|
|
if (!this->IsWithinTemporalBoundary(time))
|
|
{
|
|
status.SetFail();
|
|
status.SetTemporalBounds();
|
|
}
|
|
|
|
this->Locator.FindCell(point, cellId, parametric);
|
|
if (cellId == -1)
|
|
{
|
|
status.SetFail();
|
|
status.SetSpatialBounds();
|
|
}
|
|
else if (this->InGhostCell(cellId))
|
|
{
|
|
status.SetFail();
|
|
status.SetInGhostCell();
|
|
status.SetSpatialBounds();
|
|
}
|
|
|
|
//If initial checks ok, then do the evaluation.
|
|
if (status.CheckOk())
|
|
{
|
|
vtkm::UInt8 cellShape;
|
|
vtkm::IdComponent nVerts;
|
|
vtkm::VecVariable<vtkm::Id, 8> ptIndices;
|
|
vtkm::VecVariable<vtkm::Vec3f, 8> fieldValues;
|
|
InterpolationHelper->GetCellInfo(cellId, cellShape, nVerts, ptIndices);
|
|
|
|
this->Field->GetValue(ptIndices, nVerts, parametric, cellShape, out);
|
|
status.SetOk();
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
private:
|
|
VTKM_EXEC bool InGhostCell(const vtkm::Id& cellId) const
|
|
{
|
|
if (this->HaveGhostCells && cellId != -1)
|
|
return GhostCells.Get(cellId) == vtkm::CellClassification::GHOST;
|
|
|
|
return false;
|
|
}
|
|
|
|
using GhostCellPortal = typename vtkm::cont::ArrayHandle<vtkm::UInt8>::ReadPortalType;
|
|
|
|
vtkm::Bounds Bounds;
|
|
const vtkm::worklet::particleadvection::ExecutionField* Field;
|
|
GhostCellPortal GhostCells;
|
|
bool HaveGhostCells;
|
|
const vtkm::exec::CellInterpolationHelper* InterpolationHelper;
|
|
typename vtkm::cont::CellLocatorGeneral::ExecObjType Locator;
|
|
};
|
|
|
|
template <typename FieldType>
|
|
class GridEvaluator : public vtkm::cont::ExecutionObjectBase
|
|
{
|
|
public:
|
|
using UniformType = vtkm::cont::ArrayHandleUniformPointCoordinates;
|
|
using AxisHandle = vtkm::cont::ArrayHandle<vtkm::FloatDefault>;
|
|
using RectilinearType =
|
|
vtkm::cont::ArrayHandleCartesianProduct<AxisHandle, AxisHandle, AxisHandle>;
|
|
using Structured2DType = vtkm::cont::CellSetStructured<2>;
|
|
using Structured3DType = vtkm::cont::CellSetStructured<3>;
|
|
using GhostCellArrayType = vtkm::cont::ArrayHandle<vtkm::UInt8>;
|
|
|
|
VTKM_CONT
|
|
GridEvaluator() = default;
|
|
|
|
VTKM_CONT
|
|
GridEvaluator(const vtkm::cont::DataSet& dataSet, const FieldType& field)
|
|
: Bounds(dataSet.GetCoordinateSystem().GetBounds())
|
|
, Field(field)
|
|
, GhostCellArray()
|
|
{
|
|
this->InitializeLocator(dataSet.GetCoordinateSystem(), dataSet.GetCellSet());
|
|
|
|
if (dataSet.HasCellField("vtkmGhostCells"))
|
|
{
|
|
auto arr = dataSet.GetCellField("vtkmGhostCells").GetData();
|
|
if (arr.IsType<GhostCellArrayType>())
|
|
this->GhostCellArray = arr.AsArrayHandle<GhostCellArrayType>();
|
|
else
|
|
throw vtkm::cont::ErrorInternal("vtkmGhostCells not of type vtkm::UInt8");
|
|
}
|
|
}
|
|
|
|
VTKM_CONT
|
|
GridEvaluator(const vtkm::cont::CoordinateSystem& coordinates,
|
|
const vtkm::cont::DynamicCellSet& cellset,
|
|
const FieldType& field)
|
|
: Bounds(coordinates.GetBounds())
|
|
, Field(field)
|
|
, GhostCellArray()
|
|
{
|
|
this->InitializeLocator(coordinates, cellset);
|
|
}
|
|
|
|
VTKM_CONT ExecutionGridEvaluator<FieldType> PrepareForExecution(
|
|
vtkm::cont::DeviceAdapterId device,
|
|
vtkm::cont::Token& token) const
|
|
{
|
|
return ExecutionGridEvaluator<FieldType>(this->Locator,
|
|
this->InterpolationHelper,
|
|
this->Bounds,
|
|
this->Field,
|
|
this->GhostCellArray,
|
|
device,
|
|
token);
|
|
}
|
|
|
|
private:
|
|
VTKM_CONT void InitializeLocator(const vtkm::cont::CoordinateSystem& coordinates,
|
|
const vtkm::cont::DynamicCellSet& cellset)
|
|
{
|
|
this->Locator.SetCoordinates(coordinates);
|
|
this->Locator.SetCellSet(cellset);
|
|
this->Locator.Update();
|
|
if (cellset.IsSameType(Structured2DType()) || cellset.IsSameType(Structured3DType()))
|
|
{
|
|
vtkm::cont::StructuredCellInterpolationHelper interpolationHelper(cellset);
|
|
this->InterpolationHelper =
|
|
std::make_shared<vtkm::cont::StructuredCellInterpolationHelper>(interpolationHelper);
|
|
}
|
|
else if (cellset.IsSameType(vtkm::cont::CellSetSingleType<>()))
|
|
{
|
|
vtkm::cont::SingleCellTypeInterpolationHelper interpolationHelper(cellset);
|
|
this->InterpolationHelper =
|
|
std::make_shared<vtkm::cont::SingleCellTypeInterpolationHelper>(interpolationHelper);
|
|
}
|
|
else if (cellset.IsSameType(vtkm::cont::CellSetExplicit<>()))
|
|
{
|
|
vtkm::cont::ExplicitCellInterpolationHelper interpolationHelper(cellset);
|
|
this->InterpolationHelper =
|
|
std::make_shared<vtkm::cont::ExplicitCellInterpolationHelper>(interpolationHelper);
|
|
}
|
|
else
|
|
throw vtkm::cont::ErrorInternal("Unsupported cellset type.");
|
|
}
|
|
|
|
vtkm::Bounds Bounds;
|
|
FieldType Field;
|
|
GhostCellArrayType GhostCellArray;
|
|
std::shared_ptr<vtkm::cont::CellInterpolationHelper> InterpolationHelper;
|
|
vtkm::cont::CellLocatorGeneral Locator;
|
|
};
|
|
|
|
} //namespace particleadvection
|
|
} //namespace worklet
|
|
} //namespace vtkm
|
|
|
|
#endif // vtk_m_worklet_particleadvection_GridEvaluators_h
|