Skip to content

Commit

Permalink
adding get_attribute with tools for finding missing attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
mtao committed Nov 23, 2024
1 parent 266927b commit 78007f5
Show file tree
Hide file tree
Showing 10 changed files with 401 additions and 210 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
#include "AttributeDescription.hpp"
#include <nlohmann/json.hpp>

#include <wmtk/components/utils/json_serialize_enum.hpp>
namespace wmtk::attribute {
// TODO: this definitely will cause a conflict someday if someone else wants to serialize
// attributetype
NLOHMANN_JSON_SERIALIZE_ENUM(
WMTK_NLOHMANN_JSON_SERIALIZE_ENUM(
AttributeType,
{
{AttributeType::Char, "char"},
Expand All @@ -31,18 +32,39 @@ NLOHMANN_JSON_SERIALIZE_ENUM(
} // namespace
WMTK_NLOHMANN_JSON_FRIEND_TO_JSON_PROTOTYPE(AttributeDescription)
{
WMTK_NLOHMANN_ASSIGN_TYPE_TO_JSON(path, dimension, type);
WMTK_NLOHMANN_ASSIGN_TYPE_TO_JSON(path);
if (nlohmann_json_t.dimension.has_value()) {
nlohmann_json_j["dimension"] = nlohmann_json_t.dimension.value();
}
if (nlohmann_json_t.type.has_value()) {
nlohmann_json_j["type"] = nlohmann_json_t.type.value();
}
}
WMTK_NLOHMANN_JSON_FRIEND_FROM_JSON_PROTOTYPE(AttributeDescription)
{
WMTK_NLOHMANN_ASSIGN_TYPE_FROM_JSON(path, dimension, type);
if (nlohmann_json_j.is_string()) {
nlohmann_json_t.path = nlohmann_json_j.get<std::string>();

Check warning on line 46 in components/multimesh/src/wmtk/components/multimesh/utils/AttributeDescription.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/AttributeDescription.cpp#L46

Added line #L46 was not covered by tests
} else {
nlohmann_json_t.path = nlohmann_json_j["path"];
}
if (nlohmann_json_j.contains("dimension")) {
nlohmann_json_t.dimension = nlohmann_json_j["dimension"];
}
if (nlohmann_json_j.contains("type")) {
nlohmann_json_t.type = nlohmann_json_j["type"];
}
}

PrimitiveType AttributeDescription::primitive_type() const
std::optional<PrimitiveType> AttributeDescription::primitive_type() const
{
assert(dimension < 4);
if (this->dimension.has_value()) {
int8_t d = this->dimension.value();
assert(d < 4);

return get_primitive_type_from_id(dimension);
return get_primitive_type_from_id(d);
} else {
return {};

Check warning on line 66 in components/multimesh/src/wmtk/components/multimesh/utils/AttributeDescription.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/AttributeDescription.cpp#L66

Added line #L66 was not covered by tests
}
}

} // namespace wmtk::components::multimesh::utils
Original file line number Diff line number Diff line change
@@ -1,28 +1,33 @@
#pragma once
#include <compare>
#include <optional>
#include <wmtk/PrimitiveType.hpp>
#include <wmtk/attribute/AttributeType.hpp>
#include <wmtk/components/utils/json_macros.hpp>

namespace wmtk::attribute {
WMTK_NLOHMANN_JSON_DECLARATION(AttributeType)
}

namespace wmtk::components::multimesh::utils {


// the minimal information to uniquely extract an attribute handle
struct AttributeDescription
{
// Avoiding defining any constructors to enable aggregate construction
//AttributeDescription() = default;
//AttributeDescription(const AttributeDescription&) = default;
//AttributeDescription(AttributeDescription&&) = default;
//AttributeDescription& operator=(const AttributeDescription&) = default;
//AttributeDescription& operator=(AttributeDescription&&) = default;
// AttributeDescription() = default;
// AttributeDescription(const AttributeDescription&) = default;
// AttributeDescription(AttributeDescription&&) = default;
// AttributeDescription& operator=(const AttributeDescription&) = default;
// AttributeDescription& operator=(AttributeDescription&&) = default;
//~AttributeDescription() = default;

std::string path;
uint8_t dimension; // internally the primitive type
attribute::AttributeType type;
std::optional<uint8_t> dimension;
std::optional<attribute::AttributeType> type;

PrimitiveType primitive_type() const;
std::optional<PrimitiveType> primitive_type() const;

auto operator<=>(const AttributeDescription&) const -> std::strong_ordering;
auto operator==(const AttributeDescription&) const -> bool;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,76 @@
#include "get_attribute.hpp"
#include <ranges>
#include <wmtk/Mesh.hpp>
#include <wmtk/utils/primitive_range.hpp>
#include "..//MeshCollection.hpp"
#include "../NamedMultiMesh.hpp"
#include "AttributeDescription.hpp"
#include "get_attribute.hpp"
#include "wmtk/utils/Logger.hpp"

namespace wmtk::components::multimesh::utils {
class attribute_missing_error : public std::range_error
{
public:
static std::string make_message(

Check warning on line 16 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L16

Added line #L16 was not covered by tests
std::string path,
std::optional<uint8_t> dimension,
std::optional<attribute::AttributeType> type)
{
std::string typestr;

Check warning on line 21 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L21

Added line #L21 was not covered by tests
if (type.has_value()) {
nlohmann::json j;
j = type.value(); // just using the fact we can generate a strnig for this using json

Check warning on line 24 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L23-L24

Added lines #L23 - L24 were not covered by tests
// to get a printable string
typestr = j;
}

Check warning on line 27 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L26-L27

Added lines #L26 - L27 were not covered by tests
if (type.has_value() && dimension.has_value()) {
return fmt::format(

Check warning on line 29 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L29

Added line #L29 was not covered by tests
"Could not find attribute named {} on {}-simplices of type {}",
path,
dimension.value(),
typestr);

Check warning on line 33 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L33

Added line #L33 was not covered by tests
} else if (type.has_value()) {
return fmt::format(

Check warning on line 35 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L35

Added line #L35 was not covered by tests
"Could not find attribute named {} on {}-simplices",
path,
dimension.value());

Check warning on line 38 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L38

Added line #L38 was not covered by tests
} else if (dimension.has_value()) {
return fmt::format("Could not find attribute named {} of type {}", path, typestr);

Check warning on line 40 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L40

Added line #L40 was not covered by tests
} else {
return fmt::format("Could not find attribute named {}", path);

Check warning on line 42 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L42

Added line #L42 was not covered by tests
}
}
static std::string make_message(const AttributeDescription& ad)

Check warning on line 45 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L44-L45

Added lines #L44 - L45 were not covered by tests
{
return make_message(ad.path, ad.dimension, ad.type);

Check warning on line 47 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L47

Added line #L47 was not covered by tests
}

attribute_missing_error(const std::string_view& message, const AttributeDescription& ad)
: std::range_error(std::string(message))
, description(ad)
{}
attribute_missing_error(const AttributeDescription& ad)
: attribute_missing_error(make_message(ad), ad)
{}
attribute_missing_error(

Check warning on line 57 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L50-L57

Added lines #L50 - L57 were not covered by tests
const std::string_view& path,
const std::optional<uint8_t>& dimension,
const std::optional<attribute::AttributeType>& type)
: attribute_missing_error(AttributeDescription(std::string(path), dimension, type))
{}
attribute_missing_error(

Check warning on line 63 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L61-L63

Added lines #L61 - L63 were not covered by tests
const std::string_view& path,
const std::optional<PrimitiveType>& pt,
const std::optional<attribute::AttributeType>& type)
: attribute_missing_error(

Check warning on line 67 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L67

Added line #L67 was not covered by tests
path,
pt.has_value() ? std::optional<uint8_t>{wmtk::get_primitive_type_id(pt.value())}

Check warning on line 69 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L69

Added line #L69 was not covered by tests
: std::optional<uint8_t>{},
type)

Check warning on line 71 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L71

Added line #L71 was not covered by tests
{}
AttributeDescription description;
};


namespace detail {
Expand Down Expand Up @@ -66,7 +129,14 @@ template <typename T>
wmtk::attribute::MeshAttributeHandle
get_attribute(const Mesh& mesh, const std::string_view& name, PrimitiveType pt)
{
return mesh.get_attribute_handle<T>(std::string(name), pt);
if (mesh.has_attribute<T>(std::string(name), pt)) {
return mesh.get_attribute_handle<T>(std::string(name), pt);
} else {
throw attribute_missing_error(
std::string(name),
wmtk::get_primitive_type_id(pt),
wmtk::attribute ::attribute_type_enum_from_type<T>());

Check warning on line 138 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L135-L138

Added lines #L135 - L138 were not covered by tests
}
}

wmtk::attribute::MeshAttributeHandle get_attribute(
Expand All @@ -92,6 +162,50 @@ wmtk::attribute::MeshAttributeHandle get_attribute(
}
return {};

Check warning on line 163 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L163

Added line #L163 was not covered by tests
}
wmtk::attribute::MeshAttributeHandle get_attribute(
const Mesh& mesh,
const std::string_view& name,
std::optional<PrimitiveType> pt,
std::optional<attribute::AttributeType> type)
{
using AT = attribute::AttributeType;
// This order matches wmtk::components::utils::get_attributes
constexpr static std::array<AT, 4> types{{AT::Char, AT::Int64, AT::Double, AT::Rational}};
// constexpr static std::array<AT, 4> types{{AT::Int64, AT::Double, AT::Char, AT::Rational}};
if (pt.has_value() && type.has_value()) {
return get_attribute(mesh, name, pt.value(), type.value());
} else if (pt.has_value()) {
for (AT at : types) {
try {
return get_attribute(mesh, name, pt.value(), at);
} catch (const attribute_missing_error& e) {
continue;
}

Check warning on line 183 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L179-L183

Added lines #L179 - L183 were not covered by tests
}
} else if (type.has_value()) {
for (PrimitiveType p : wmtk::utils::primitive_below(mesh.top_simplex_type())) {
try {
return get_attribute(mesh, name, p, type.value());
} catch (const attribute_missing_error& e) {
continue;

Check warning on line 190 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L187-L190

Added lines #L187 - L190 were not covered by tests
}
}
} else {
for (AT at : types) {
for (PrimitiveType p : wmtk::utils::primitive_below(mesh.top_simplex_type())) {
try {
return get_attribute(mesh, name, p, at);
} catch (const attribute_missing_error& e) {
continue;
}
}

Check warning on line 201 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L196-L201

Added lines #L196 - L201 were not covered by tests
}
}


throw attribute_missing_error(name, pt, type);

Check warning on line 206 in components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/utils/get_attribute.cpp#L206

Added line #L206 was not covered by tests
return {};
}
} // namespace detail

wmtk::attribute::MeshAttributeHandle get_attribute(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class Mesh;
namespace components::multimesh {
class NamedMultiMesh;
class MeshCollection;
}
} // namespace components::multimesh
} // namespace wmtk

namespace wmtk::components::multimesh {
Expand All @@ -21,6 +21,9 @@ struct AttributeDescription;
// * simplex (int, dimension attribute belongs to
// if type and simplex are missing code will search in lexicographical of (primitive_type, type)
// where double < int < char < rational for type
//
// this is somewhat redundant to wmtk::components::utils::get_attributes, but is designed around
// supporting multimesh paths.

wmtk::attribute::MeshAttributeHandle get_attribute(
const NamedMultiMesh& mesh,
Expand All @@ -32,5 +35,5 @@ wmtk::attribute::MeshAttributeHandle get_attribute(
const Mesh& mesh,
const AttributeDescription& description);

}
} // namespace wmtk::components::multimesh::utils
} // namespace utils
} // namespace wmtk::components::multimesh
7 changes: 6 additions & 1 deletion components/multimesh/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@

add_component_test(wmtk::${COMPONENT_NAME} named_multimesh.cpp)
add_component_test(wmtk::${COMPONENT_NAME}
named_multimesh.cpp
get_attributes.cpp
utils.hpp
utils.cpp
)

target_link_libraries(${WMTK_COMPONENT_TEST_TARGET} PRIVATE wmtk::input)
Loading

0 comments on commit 78007f5

Please sign in to comment.