//============================================================================ // 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. //============================================================================ #include #include #include #include #include #include namespace vtkm { namespace cont { /// constructors for points / whole mesh VTKM_CONT Field::Field(std::string name, Association association, const vtkm::cont::UnknownArrayHandle& data) : Name(name) , FieldAssociation(association) , Data(data) , Range() , ModifiedFlag(true) { } VTKM_CONT Field::Field(const vtkm::cont::Field& src) : Name(src.Name) , FieldAssociation(src.FieldAssociation) , Data(src.Data) , Range(src.Range) , ModifiedFlag(src.ModifiedFlag) { } VTKM_CONT Field::Field(vtkm::cont::Field&& src) noexcept : Name(std::move(src.Name)) , FieldAssociation(std::move(src.FieldAssociation)) , Data(std::move(src.Data)) , Range(std::move(src.Range)) , ModifiedFlag(std::move(src.ModifiedFlag)) { } VTKM_CONT Field& Field::operator=(const vtkm::cont::Field& src) { this->Name = src.Name; this->FieldAssociation = src.FieldAssociation; this->Data = src.Data; this->Range = src.Range; this->ModifiedFlag = src.ModifiedFlag; return *this; } VTKM_CONT Field& Field::operator=(vtkm::cont::Field&& src) noexcept { this->Name = std::move(src.Name); this->FieldAssociation = std::move(src.FieldAssociation); this->Data = std::move(src.Data); this->Range = std::move(src.Range); this->ModifiedFlag = std::move(src.ModifiedFlag); return *this; } VTKM_CONT void Field::PrintSummary(std::ostream& out) const { out << " " << this->Name; out << " assoc= "; switch (this->GetAssociation()) { case Association::Any: out << "Any "; break; case Association::WholeDataSet: out << "WholeDataSet "; break; case Association::Points: out << "Points "; break; case Association::Cells: out << "Cells "; break; case Association::Partitions: out << "Partitions "; break; case Association::Global: out << "Global "; break; } this->Data.PrintSummary(out); } VTKM_CONT Field::~Field() {} VTKM_CONT const vtkm::cont::UnknownArrayHandle& Field::GetData() const { return this->Data; } VTKM_CONT vtkm::cont::UnknownArrayHandle& Field::GetData() { this->ModifiedFlag = true; return this->Data; } VTKM_CONT const vtkm::cont::ArrayHandle& Field::GetRange() const { VTKM_LOG_SCOPE(vtkm::cont::LogLevel::Perf, "Field::GetRange"); if (this->ModifiedFlag) { this->Range = vtkm::cont::ArrayRangeCompute(this->Data); this->ModifiedFlag = false; } return this->Range; } VTKM_CONT void Field::GetRange(vtkm::Range* range) const { this->GetRange(); const vtkm::Id length = this->Range.GetNumberOfValues(); auto portal = this->Range.ReadPortal(); for (vtkm::Id i = 0; i < length; ++i) { range[i] = portal.Get(i); } } VTKM_CONT void Field::SetData(const vtkm::cont::UnknownArrayHandle& newdata) { this->Data = newdata; this->ModifiedFlag = true; } namespace { struct CheckArrayType { template void operator()(vtkm::List, const vtkm::cont::UnknownArrayHandle& data, bool& found) const { if (data.CanConvert>()) { found = true; } } }; } // anonymous namespace bool Field::IsSupportedType() const { bool found = false; vtkm::ListForEach( CheckArrayType{}, vtkm::cont::internal::ListAllArrayTypes{}, this->Data, found); return found; } namespace { struct CheckStorageType { template void operator()(S, const vtkm::cont::UnknownArrayHandle& data, bool& found) const { if (data.IsStorageType()) { found = true; } } }; // This worklet is used in lieu of ArrayCopy because the use of ArrayHandleRecombineVec // can throw off the casting in implementations of ArrayCopy. struct CopyWorklet : vtkm::worklet::WorkletMapField { using ControlSignature = void(FieldIn, FieldOut); using ExecutionSignature = void(_1, _2); template VTKM_EXEC_CONT void operator()(const InType& in, OutType& out) const { VTKM_ASSERT(in.GetNumberOfComponents() == out.GetNumberOfComponents()); for (vtkm::IdComponent cIndex = 0; cIndex < in.GetNumberOfComponents(); ++cIndex) { out[cIndex] = static_cast(in[cIndex]); } } }; struct CopyToFloatArray { template void operator()(const ArrayType& inArray, vtkm::cont::UnknownArrayHandle& outArray) const { vtkm::cont::Invoker invoke; invoke(CopyWorklet{}, inArray, outArray.ExtractArrayFromComponents()); } }; } // anonymous namespace vtkm::cont::UnknownArrayHandle Field::GetDataAsDefaultFloat() const { if (this->Data.IsBaseComponentType()) { bool supportedStorage = false; vtkm::ListForEach( CheckStorageType{}, VTKM_DEFAULT_STORAGE_LIST{}, this->Data, supportedStorage); if (supportedStorage) { // Array is already float default and supported storage. No better conversion can be done. return this->Data; } } VTKM_LOG_SCOPE(vtkm::cont::LogLevel::Info, "Converting field '%s' to default floating point.", this->GetName().c_str()); vtkm::cont::UnknownArrayHandle outArray = this->Data.NewInstanceFloatBasic(); outArray.Allocate(this->Data.GetNumberOfValues()); this->Data.CastAndCallWithExtractedArray(CopyToFloatArray{}, outArray); return outArray; } vtkm::cont::UnknownArrayHandle Field::GetDataWithExpectedTypes() const { if (this->IsSupportedType()) { return this->Data; } else { return this->GetDataAsDefaultFloat(); } } void Field::ConvertToExpected() { this->SetData(this->GetDataWithExpectedTypes()); } } } // namespace vtkm::cont namespace mangled_diy_namespace { void Serialization::save(BinaryBuffer& bb, const vtkm::cont::Field& field) { vtkmdiy::save(bb, field.GetName()); vtkmdiy::save(bb, static_cast(field.GetAssociation())); vtkmdiy::save(bb, field.GetData()); } void Serialization::load(BinaryBuffer& bb, vtkm::cont::Field& field) { std::string name; vtkmdiy::load(bb, name); int assocVal = 0; vtkmdiy::load(bb, assocVal); auto assoc = static_cast(assocVal); vtkm::cont::UnknownArrayHandle data; vtkmdiy::load(bb, data); field = vtkm::cont::Field(name, assoc, data); } } // namespace diy