//============================================================================ // 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 Sandia Corporation. // Copyright 2014 UT-Battelle, LLC. // Copyright 2014 Los Alamos National Security. // // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, // 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 #include #include namespace { //----------------------------------------------------------------------------- template struct PointGrad { PointGrad(const vtkm::cont::CoordinateSystem& coords, const vtkm::cont::ArrayHandle< T, S>& field, vtkm::cont::ArrayHandle< vtkm::Vec >* result): Points(&coords), InField(&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 vtkm::filter::ApplyPolicy(*this->Points, this->Policy), *this->InField, *this->Result); } vtkm::filter::PolicyBase Policy; const vtkm::cont::CoordinateSystem* const Points; const vtkm::cont::ArrayHandle* const InField; vtkm::cont::ArrayHandle< vtkm::Vec >* Result; private: void operator=(const PointGrad &) = delete; }; //----------------------------------------------------------------------------- template inline void add_field( vtkm::filter::ResultField& result, const HandleType& handle, const std::string name) { const vtkm::cont::Field::AssociationEnum assoc = result.GetField().GetAssociation(); if ((assoc == vtkm::cont::Field::ASSOC_WHOLE_MESH) || (assoc == vtkm::cont::Field::ASSOC_POINTS)) { vtkm::cont::Field field(name, assoc, handle); result.GetDataSet().AddField(field); } else { vtkm::cont::Field field(name, assoc, result.GetField().GetAssocCellSet(), handle); result.GetDataSet().AddField(field); } } //----------------------------------------------------------------------------- template inline void add_extra_vec_fields( const vtkm::cont::ArrayHandle< vtkm::Vec< vtkm::Vec, 3>, S> &inField, const vtkm::filter::Gradient* const filter, vtkm::filter::ResultField& result, const DeviceAdapter&) { if(filter->GetComputeDivergence()) { vtkm::cont::ArrayHandle< T > divergence; vtkm::worklet::DispatcherMapField< vtkm::worklet::Divergence, DeviceAdapter > dispatcher; dispatcher.Invoke(inField, divergence); add_field(result, divergence, filter->GetDivergenceName()); } if(filter->GetComputeVorticity()) { vtkm::cont::ArrayHandle< vtkm::Vec > vorticity; vtkm::worklet::DispatcherMapField< vtkm::worklet::Vorticity, DeviceAdapter > dispatcher; dispatcher.Invoke(inField, vorticity); add_field(result, vorticity, filter->GetVorticityName()); } if(filter->GetComputeQCriterion()) { vtkm::cont::ArrayHandle< T > qc; vtkm::worklet::DispatcherMapField< vtkm::worklet::QCriterion, DeviceAdapter > dispatcher; dispatcher.Invoke(inField, qc); add_field(result, qc, filter->GetQCriterionName()); } } template inline void add_extra_vec_fields( const vtkm::cont::ArrayHandle< T, S> &, const vtkm::filter::Gradient* const, vtkm::filter::ResultField&, const DeviceAdapter&) { //not a vector array handle so add nothing } } //namespace namespace vtkm { namespace filter { //----------------------------------------------------------------------------- Gradient::Gradient(): ComputePointGradient(false), ComputeVorticity(false), ComputeQCriterion(false), DivergenceName("Divergence"), VorticityName("Vorticity"), QCriterionName("QCriterion") { } //----------------------------------------------------------------------------- template inline vtkm::filter::ResultField Gradient::DoExecute( const vtkm::cont::DataSet &input, const vtkm::cont::ArrayHandle &inField, const vtkm::filter::FieldMetadata &fieldMetadata, const vtkm::filter::PolicyBase& policy, const DeviceAdapter& adapter) { if(!fieldMetadata.IsPointField()) { //we currently only support point fields, as we need to write the //worklet to efficiently map a cell field to the points of a cell //without doing a memory explosion return vtkm::filter::ResultField(); } const vtkm::cont::DynamicCellSet& cells = input.GetCellSet(this->GetActiveCellSetIndex()); const vtkm::cont::CoordinateSystem& coords = input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()); vtkm::cont::Field::AssociationEnum fieldAssociation; std::string outputName = this->GetOutputFieldName(); if (outputName.empty()) { outputName = "Gradients"; } //todo: we need to ask the policy what storage type we should be using //If the input is implicit, we should know what to fall back to vtkm::cont::ArrayHandle< vtkm::Vec > outArray; if(this->ComputePointGradient) { PointGrad func(coords, inField, &outArray); vtkm::cont::CastAndCall( vtkm::filter::ApplyPolicy(cells, policy), func); fieldAssociation = vtkm::cont::Field::ASSOC_POINTS; } else { vtkm::worklet::DispatcherMapTopology< vtkm::worklet::CellGradient, DeviceAdapter > dispatcher; dispatcher.Invoke( vtkm::filter::ApplyPolicy(cells, policy), vtkm::filter::ApplyPolicy(coords, policy), inField, outArray); fieldAssociation = vtkm::cont::Field::ASSOC_CELL_SET; } vtkm::filter::ResultField result(input, outArray, outputName, fieldAssociation, cells.GetName()); //Add the vorticity and qcriterion fields if they are enabled to the result add_extra_vec_fields(outArray, this, result, adapter); return result; } } } // namespace vtkm::filter