//============================================================================ // 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_Gradient_h #define vtk_m_worklet_Gradient_h #include #include #include #include #include #include #include #include #include #include namespace vtkm { namespace worklet { template struct GradientOutputFields; namespace gradient { //----------------------------------------------------------------------------- template struct DeducedPointGrad { DeducedPointGrad(const CoordinateSystem& coords, const vtkm::cont::ArrayHandle& field, GradientOutputFields* result) : Points(&coords) , Field(&field) , Result(result) { } template void operator()(const CellSetType& cellset) const { vtkm::worklet::DispatcherMapTopology dispatcher; dispatcher.Invoke(cellset, //topology to iterate on a per point basis cellset, //whole cellset in *this->Points, *this->Field, *this->Result); } void operator()(const vtkm::cont::CellSetStructured<3>& cellset) const { vtkm::worklet::DispatcherPointNeighborhood dispatcher; dispatcher.Invoke(cellset, //topology to iterate on a per point basis *this->Points, *this->Field, *this->Result); } template void operator()(const vtkm::cont::CellSetPermutation, PermIterType>& cellset) const { vtkm::worklet::DispatcherPointNeighborhood dispatcher; dispatcher.Invoke(cellset, //topology to iterate on a per point basis *this->Points, *this->Field, *this->Result); } void operator()(const vtkm::cont::CellSetStructured<2>& cellset) const { vtkm::worklet::DispatcherPointNeighborhood dispatcher; dispatcher.Invoke(cellset, //topology to iterate on a per point basis *this->Points, *this->Field, *this->Result); } template void operator()(const vtkm::cont::CellSetPermutation, PermIterType>& cellset) const { vtkm::worklet::DispatcherPointNeighborhood dispatcher; dispatcher.Invoke(cellset, //topology to iterate on a per point basis *this->Points, *this->Field, *this->Result); } const CoordinateSystem* const Points; const vtkm::cont::ArrayHandle* const Field; GradientOutputFields* Result; private: void operator=(const DeducedPointGrad&) = delete; }; } //namespace gradient template struct GradientOutputFields : public vtkm::cont::ExecutionObjectBase { using ValueType = T; using BaseTType = typename vtkm::VecTraits::BaseComponentType; template struct ExecutionTypes { using Portal = vtkm::exec::GradientOutput; }; GradientOutputFields() : Gradient() , Divergence() , Vorticity() , QCriterion() , StoreGradient(true) , ComputeDivergence(false) , ComputeVorticity(false) , ComputeQCriterion(false) { } GradientOutputFields(bool store, bool divergence, bool vorticity, bool qc) : Gradient() , Divergence() , Vorticity() , QCriterion() , StoreGradient(store) , ComputeDivergence(divergence) , ComputeVorticity(vorticity) , ComputeQCriterion(qc) { } /// Add divergence field to the output data. /// The input array must have 3 components in order to compute this. /// The default is off. void SetComputeDivergence(bool enable) { ComputeDivergence = enable; } bool GetComputeDivergence() const { return ComputeDivergence; } /// Add voriticity/curl field to the output data. /// The input array must have 3 components in order to compute this. /// The default is off. void SetComputeVorticity(bool enable) { ComputeVorticity = enable; } bool GetComputeVorticity() const { return ComputeVorticity; } /// Add Q-criterion field to the output data. /// The input array must have 3 components in order to compute this. /// The default is off. void SetComputeQCriterion(bool enable) { ComputeQCriterion = enable; } bool GetComputeQCriterion() const { return ComputeQCriterion; } /// Add gradient field to the output data. /// The input array must have 3 components in order to disable this. /// The default is on. void SetComputeGradient(bool enable) { StoreGradient = enable; } bool GetComputeGradient() const { return StoreGradient; } //todo fix this for scalar vtkm::exec::GradientOutput PrepareForOutput(vtkm::Id size) { vtkm::exec::GradientOutput portal(this->StoreGradient, this->ComputeDivergence, this->ComputeVorticity, this->ComputeQCriterion, this->Gradient, this->Divergence, this->Vorticity, this->QCriterion, size); return portal; } vtkm::cont::ArrayHandle> Gradient; vtkm::cont::ArrayHandle Divergence; vtkm::cont::ArrayHandle> Vorticity; vtkm::cont::ArrayHandle QCriterion; private: bool StoreGradient; bool ComputeDivergence; bool ComputeVorticity; bool ComputeQCriterion; }; class PointGradient { public: template vtkm::cont::ArrayHandle> Run(const CellSetType& cells, const CoordinateSystem& coords, const vtkm::cont::ArrayHandle& field) { vtkm::worklet::GradientOutputFields extraOutput(true, false, false, false); return this->Run(cells, coords, field, extraOutput); } template vtkm::cont::ArrayHandle> Run(const CellSetType& cells, const CoordinateSystem& coords, const vtkm::cont::ArrayHandle& field, GradientOutputFields& extraOutput) { //we are using cast and call here as we pass the cells twice to the invoke //and want the type resolved once before hand instead of twice //by the dispatcher ( that will cost more in time and binary size ) gradient::DeducedPointGrad func(coords, field, &extraOutput); vtkm::cont::CastAndCall(cells, func); return extraOutput.Gradient; } }; class CellGradient { public: template vtkm::cont::ArrayHandle> Run(const CellSetType& cells, const CoordinateSystem& coords, const vtkm::cont::ArrayHandle& field) { vtkm::worklet::GradientOutputFields extra(true, false, false, false); return this->Run(cells, coords, field, extra); } template vtkm::cont::ArrayHandle> Run(const CellSetType& cells, const CoordinateSystem& coords, const vtkm::cont::ArrayHandle& field, GradientOutputFields& extraOutput) { vtkm::worklet::DispatcherMapTopology dispatcher; dispatcher.Invoke(cells, coords, field, extraOutput); return extraOutput.Gradient; } }; } } // namespace vtkm::worklet #endif