Program Listing for File point_cloud.h
↰ Return to documentation for file (src/pcms/field/evaluator/point_cloud.h)
#ifndef PCMS_POINT_CLOUD_EVALUATOR_FACTORY_H
#define PCMS_POINT_CLOUD_EVALUATOR_FACTORY_H
#include "pcms/field/field_evaluator_factory.h"
#include "pcms/field/out_of_bounds_policy.h"
#include "pcms/field/point_evaluator.h"
#include "pcms/field/field_data.h"
#include "pcms/field/evaluation_request.h"
#include "pcms/field/evaluator/mls_options.h"
#include "pcms/field/evaluator/mls_point_cloud.h"
#include "pcms/localization/localization_path_selection.h"
#include "pcms/localization/mesh_localization.h"
#include "pcms/localization/localization_factory.h"
#include "pcms/utility/assert.h"
#include "pcms/utility/omega_h_array_utils.h"
#include <Omega_h_array.hpp>
#include <memory>
#include <string>
namespace pcms
{
class PointCloudEvaluatorFactory : public FieldEvaluatorFactory<Real>
{
public:
PointCloudEvaluatorFactory(std::shared_ptr<const FieldLayout> layout,
std::shared_ptr<LocalizationFactory> localization,
MLSOptions options = {})
: layout_(std::move(layout)),
localization_(std::move(localization)),
options_(options)
{
}
const FieldLayout& GetLayout() const override { return *layout_; }
bool HasDOFHolderCoordinates() const override { return true; }
CoordinateView<DeviceMemorySpace> GetDOFHolderCoordinates() const override
{
return layout_->GetDOFHolderCoordinates();
}
bool SupportsNearestBoundary() const override { return false; }
std::unique_ptr<PointEvaluator<Real>> CreatePointEvaluator(
const EvaluationRequest& request) const override
{
const auto coords = request.coords;
// MLS distances are based on the unweighted Euclidean measure
// this is only valid with identity metric
// this almost certainly should be generalized to take metric for distances
// for now, we just check and fail so at least the user gets a warning
if (!HasIdentityMetric(*layout_->GetCoordinateSystem())) {
throw pcms_error(
"PointCloudEvaluatorFactory: MLS point-cloud evaluation requires a "
"coordinate system whose metric is the identity; got '" +
std::string(layout_->GetCoordinateSystem()->Kind()) + "'");
}
// Extract source coordinates for the MLS solve.
const auto src_view = layout_->GetDOFHolderCoordinates().GetValues();
const int dim = layout_->GetDimension();
Omega_h::Reals source_coords =
flatten_to_omega_h_reals(src_view, "src_coords");
// Extract target coordinates for the MLS solve.
const auto tgt_view = coords.GetValues();
PCMS_ALWAYS_ASSERT(static_cast<int>(tgt_view.extent(1)) == dim);
Omega_h::Reals target_coords_oh =
flatten_to_omega_h_reals(tgt_view, "tgt_coords");
SupportResults supports;
auto path =
detail::SelectLocalizationPath(*layout_, request.GetQueryLayout());
if (path == detail::LocalizationPath::CentroidToVertexAdjacencySearch) {
auto* adjacency =
dynamic_cast<const AdjacencyLocalizationFactory*>(localization_.get());
PCMS_ALWAYS_ASSERT(adjacency != nullptr);
supports = adjacency->BuildSameMeshCentroidToVertex();
} else {
supports = localization_->Build(coords);
}
return std::make_unique<MLSPointEvaluator<>>(
std::move(source_coords), std::move(target_coords_oh),
std::move(supports), dim, options_);
}
private:
std::shared_ptr<const FieldLayout> layout_;
std::shared_ptr<LocalizationFactory> localization_;
MLSOptions options_;
};
} // namespace pcms
#endif // PCMS_POINT_CLOUD_EVALUATOR_FACTORY_H