Add new files for ghost cells

This commit is contained in:
Dave Pugmire 2018-09-06 11:39:04 -04:00
parent beec402446
commit 4ae9cedead
4 changed files with 489 additions and 0 deletions

39
vtkm/GhostCell.h Normal file

@ -0,0 +1,39 @@
//============================================================================
// 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.
//
// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_Ghost_Cell_h
#define vtk_m_Ghost_Cell_h
namespace vtkm
{
enum struct CellClassification
{
NORMAL = 0, //Valid cell
DUPLICATE = 1 << 0, //Ghost cell
INVALID = 1 << 1, //Cell is invalid
UNUSED0 = 1 << 2,
UNUSED1 = 1 << 3,
UNUSED3 = 1 << 4,
UNUSED4 = 1 << 5,
UNUSED5 = 1 << 6,
};
}
#endif // vtk_m_Ghost_Cell_h

106
vtkm/filter/GhostZone.h Normal file

@ -0,0 +1,106 @@
//============================================================================
// 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.
//
// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_filter_GhostZone_h
#define vtk_m_filter_GhostZone_h
#include <vtkm/GhostCell.h>
#include <vtkm/filter/FilterDataSetWithField.h>
#include <vtkm/filter/Threshold.h>
namespace vtkm
{
namespace filter
{
struct GhostZonePolicy : vtkm::filter::PolicyBase<GhostZonePolicy>
{
using FieldTypeList = vtkm::ListTagBase<vtkm::UInt8>;
};
/// \brief Removes ghost zones
///
class GhostZone : public vtkm::filter::FilterDataSetWithField<GhostZone>
{
public:
VTKM_CONT
GhostZone();
VTKM_CONT
void RemoveAllGhost() { this->RemoveAll = true; }
VTKM_CONT
void RemoveByType(const vtkm::UInt8& vals)
{
this->RemoveAll = false;
this->RemoveVals = vals;
}
VTKM_CONT
bool GetRemoveAllGhost() const { return this->RemoveAll; }
VTKM_CONT
void ConvertOutputToUnstructured() { this->ConvertToUnstructured = true; }
VTKM_CONT
vtkm::UInt8 GetRemoveByType() const { return !this->RemoveAll; }
VTKM_CONT
vtkm::UInt8 GetRemoveType() const { return this->RemoveVals; }
VTKM_CONT
bool GetConvertOutputToUnstructured() { return this->ConvertToUnstructured; }
template <typename T, typename StorageType, typename DerivedPolicy, typename DeviceAdapter>
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input,
const vtkm::cont::ArrayHandle<T, StorageType>& field,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
DeviceAdapter tag);
//Map a new field onto the resulting dataset after running the filter
//this call is only valid
template <typename T, typename StorageType, typename DerivedPolicy, typename DeviceAdapter>
VTKM_CONT bool DoMapField(vtkm::cont::DataSet& result,
const vtkm::cont::ArrayHandle<T, StorageType>& input,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
DeviceAdapter tag);
private:
bool RemoveAll;
bool ConvertToUnstructured;
vtkm::UInt8 RemoveVals;
vtkm::worklet::Threshold Worklet;
template <typename DeviceAdapter>
VTKM_CONT vtkm::cont::CellSetExplicit<> ConvertOutputToUnstructured(
vtkm::cont::DynamicCellSet& inCells,
DeviceAdapter tag);
};
template <>
class FilterTraits<GhostZone>
{ //currently the ghostzone filter only works on uint8 data.
public:
using InputFieldTypeList = vtkm::ListTagBase<vtkm::UInt8>;
};
}
} // namespace vtkm::filter
#include <vtkm/filter/GhostZone.hxx>
#endif // vtk_m_filter_GhostZone_h

191
vtkm/filter/GhostZone.hxx Normal file

@ -0,0 +1,191 @@
//============================================================================
// 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.
//
// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/ArrayHandlePermutation.h>
#include <vtkm/cont/CellSetPermutation.h>
#include <vtkm/cont/DynamicCellSet.h>
#include <vtkm/worklet/CellDeepCopy.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
namespace
{
class RemoveAllGhosts
{
public:
VTKM_CONT
RemoveAllGhosts() {}
VTKM_EXEC bool operator()(const vtkm::UInt8& value) const { return (value == 0); }
};
class RemoveGhostByType
{
public:
VTKM_CONT
RemoveGhostByType()
: RemoveType(0)
{
}
VTKM_CONT
RemoveGhostByType(const vtkm::UInt8& val)
: RemoveType(~val)
{
}
VTKM_EXEC bool operator()(const vtkm::UInt8& value) const
{
return value == 0 || (value & RemoveType);
}
private:
vtkm::UInt8 RemoveType;
};
} // end anon namespace
namespace vtkm
{
namespace filter
{
//-----------------------------------------------------------------------------
inline VTKM_CONT GhostZone::GhostZone()
: vtkm::filter::FilterDataSetWithField<GhostZone>()
, RemoveAll(false)
, ConvertToUnstructured(false)
, RemoveVals(0)
{
this->SetActiveField("vtkmGhostCells");
}
//-----------------------------------------------------------------------------
template <typename T, typename StorageType, typename DerivedPolicy, typename DeviceAdapter>
inline VTKM_CONT vtkm::cont::DataSet GhostZone::DoExecute(
const vtkm::cont::DataSet& input,
const vtkm::cont::ArrayHandle<T, StorageType>& field,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
DeviceAdapter)
{
//get the cells and coordinates of the dataset
const vtkm::cont::DynamicCellSet& cells = input.GetCellSet(this->GetActiveCellSetIndex());
vtkm::cont::DynamicCellSet cellOut;
if (this->GetRemoveAllGhost())
cellOut = this->Worklet.Run(vtkm::filter::ApplyPolicy(cells, policy),
field,
fieldMeta.GetAssociation(),
RemoveAllGhosts(),
DeviceAdapter());
else if (this->GetRemoveByType())
cellOut = this->Worklet.Run(vtkm::filter::ApplyPolicy(cells, policy),
field,
fieldMeta.GetAssociation(),
RemoveGhostByType(this->GetRemoveType()),
DeviceAdapter());
else
throw vtkm::cont::ErrorFilterExecution("Unsupported ghost cell removal type");
vtkm::cont::DataSet output;
output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()));
if (this->GetConvertOutputToUnstructured())
{
vtkm::cont::CellSetExplicit<> explicitCells;
//vtkm::worklet::CellDeepCopy::Run(cellOut, explicitCells, DeviceAdapter());
explicitCells = this->ConvertOutputToUnstructured(cellOut, DeviceAdapter());
output.AddCellSet(explicitCells);
}
else
output.AddCellSet(cellOut);
return output;
}
//-----------------------------------------------------------------------------
template <typename T, typename StorageType, typename DerivedPolicy, typename DeviceAdapter>
inline VTKM_CONT bool GhostZone::DoMapField(vtkm::cont::DataSet& result,
const vtkm::cont::ArrayHandle<T, StorageType>& input,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<DerivedPolicy>&,
DeviceAdapter device)
{
if (fieldMeta.IsPointField())
{
//we copy the input handle to the result dataset, reusing the metadata
result.AddField(fieldMeta.AsField(input));
return true;
}
else if (fieldMeta.IsCellField())
{
vtkm::cont::ArrayHandle<T> out = this->Worklet.ProcessCellField(input, device);
result.AddField(fieldMeta.AsField(out));
return true;
}
else
{
return false;
}
}
template <typename DeviceAdapter>
inline VTKM_CONT vtkm::cont::CellSetExplicit<> GhostZone::ConvertOutputToUnstructured(
vtkm::cont::DynamicCellSet& inCells,
DeviceAdapter tag)
{
using PermStructured2d = vtkm::cont::CellSetPermutation<vtkm::cont::CellSetStructured<2>>;
using PermStructured3d = vtkm::cont::CellSetPermutation<vtkm::cont::CellSetStructured<3>>;
using PermExplicit = vtkm::cont::CellSetPermutation<vtkm::cont::CellSetExplicit<>>;
using PermExplicitSingle = vtkm::cont::CellSetPermutation<vtkm::cont::CellSetSingleType<>>;
vtkm::cont::CellSetExplicit<> explicitCells;
if (inCells.IsSameType(PermStructured2d()))
{
PermStructured2d perm = inCells.Cast<PermStructured2d>();
vtkm::worklet::CellDeepCopy::Run(perm, explicitCells, tag);
}
else if (inCells.IsSameType(PermStructured3d()))
{
PermStructured3d perm = inCells.Cast<PermStructured3d>();
vtkm::worklet::CellDeepCopy::Run(perm, explicitCells, tag);
}
else if (inCells.IsSameType(PermExplicit()))
{
PermExplicit perm = inCells.Cast<PermExplicit>();
vtkm::worklet::CellDeepCopy::Run(perm, explicitCells, tag);
}
else if (inCells.IsSameType(PermExplicitSingle()))
{
PermExplicitSingle perm = inCells.Cast<PermExplicitSingle>();
vtkm::worklet::CellDeepCopy::Run(perm, explicitCells, tag);
}
else
throw vtkm::cont::ErrorFilterExecution("Unsupported permutation cell type");
return explicitCells;
}
}
}

@ -0,0 +1,153 @@
//============================================================================
// 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.
//
// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/filter/GhostZone.h>
using vtkm::cont::testing::MakeTestDataSet;
namespace
{
static vtkm::cont::ArrayHandle<vtkm::UInt8> StructuredGhostZoneArray(vtkm::Id nx,
vtkm::Id ny,
vtkm::Id nz,
int numLayers)
{
vtkm::Id numCells = nx * ny;
if (nz > 0)
numCells *= nz;
vtkm::UInt8 normalCell = static_cast<vtkm::UInt8>(vtkm::CellClassification::NORMAL);
vtkm::UInt8 duplicateCell = static_cast<vtkm::UInt8>(vtkm::CellClassification::DUPLICATE);
vtkm::cont::ArrayHandle<vtkm::UInt8> ghosts;
ghosts.Allocate(numCells);
auto portal = ghosts.GetPortalControl();
for (vtkm::Id i = 0; i < numCells; i++)
{
if (numLayers == 0)
portal.Set(i, normalCell);
else
portal.Set(i, duplicateCell);
}
if (numLayers > 0)
{
//2D case
if (nz == 0)
{
for (vtkm::Id i = numLayers; i < nx - numLayers; i++)
for (vtkm::Id j = numLayers; j < ny - numLayers; j++)
portal.Set(i * nx + j, normalCell);
}
else
{
for (vtkm::Id i = numLayers; i < nx - numLayers; i++)
for (vtkm::Id j = numLayers; j < ny - numLayers; j++)
for (vtkm::Id k = numLayers; k < nz - numLayers; k++)
portal.Set(k * nx * ny + j * nx + i, normalCell);
}
}
return ghosts;
}
static vtkm::cont::DataSet MakeUniform(vtkm::Id numI, vtkm::Id numJ, vtkm::Id numK, int numLayers)
{
vtkm::cont::DataSetBuilderUniform dsb;
vtkm::cont::DataSet ds;
if (numK == 0)
ds = dsb.Create(vtkm::Id2(numI + 1, numJ + 1));
else
ds = dsb.Create(vtkm::Id3(numI + 1, numJ + 1, numK + 1));
vtkm::cont::ArrayHandle<vtkm::UInt8> ghosts;
ghosts = StructuredGhostZoneArray(numI, numJ, numK, numLayers);
vtkm::cont::DataSetFieldAdd dsf;
dsf.AddCellField(ds, "vtkmGhostCells", ghosts);
return ds;
}
void TestUniform()
{
std::cout << "Testing ghost cells for uniform datasets." << std::endl;
// specify some 2d tests: {numI, numJ, numGhostLayers}.
std::vector<std::vector<vtkm::Id>> tests2D = { { 4, 4, 0, 2 }, { 5, 5, 0, 3 }, { 10, 10, 0, 3 } };
for (auto& t : tests2D)
{
vtkm::Id nx = t[0], ny = t[1], nz = t[2];
int nghost = static_cast<int>(t[3]);
for (int layer = 0; layer < nghost; layer++)
{
vtkm::cont::DataSet ds = MakeUniform(nx, ny, nz, layer);
std::vector<std::string> removeType = { "all", "byType" };
for (auto& rt : removeType)
{
vtkm::filter::GhostZone ghostZoneRemoval;
if (rt == "all")
ghostZoneRemoval.RemoveAllGhost();
else if (rt == "byType")
ghostZoneRemoval.RemoveByType(
static_cast<vtkm::UInt8>(vtkm::CellClassification::DUPLICATE));
std::vector<std::string> outputType = { "permutation", "explicit" };
for (auto& ot : outputType)
{
if (ot == "explicit")
ghostZoneRemoval.ConvertOutputToUnstructured();
auto output = ghostZoneRemoval.Execute(ds, vtkm::filter::GhostZonePolicy());
vtkm::Id numCells = output.GetCellSet(0).GetNumberOfCells();
//Validate the output.
VTKM_TEST_ASSERT(output.GetNumberOfCellSets() == 1,
"Wrong number of cell sets in output");
vtkm::Id numCellsReq = (nx - 2 * layer) * (ny - 2 * layer);
if (nz != 0)
numCellsReq += (nz - 2 * layer);
VTKM_TEST_ASSERT(numCellsReq == numCells, "Wrong number of cells in output");
if (ot == "explicit")
VTKM_TEST_ASSERT(output.GetCellSet(0).IsType<vtkm::cont::CellSetExplicit<>>(),
"Wrong cell type for explicit conversion");
}
}
}
}
}
void TestGhostZone()
{
TestUniform();
}
}
int UnitTestGhostZone(int, char* [])
{
return vtkm::cont::testing::Testing::Run(TestGhostZone);
}