Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Method for using structs / json to access attributes #842

Merged
merged 10 commits into from
Nov 25, 2024
16 changes: 14 additions & 2 deletions components/multimesh/src/wmtk/components/multimesh/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,24 @@ set(SRC_FILES

NamedMultiMesh.hpp
NamedMultiMesh.cpp
utils/get_attribute.hpp
utils/get_attribute.cpp
internal/split_path.hpp

MeshCollection.hpp
MeshCollection.cpp

utils/AttributeDescription.hpp
utils/AttributeDescription.cpp

utils/get_attribute.hpp
utils/get_attribute.cpp
utils/detail/attribute_error.hpp

utils/detail/named_error_text.hpp
utils/detail/named_error_text.cpp
utils/detail/attribute_ambiguous_error.hpp
utils/detail/attribute_ambiguous_error.cpp
utils/detail/attribute_missing_error.hpp
utils/detail/attribute_missing_error.cpp
)

include(stb)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
namespace wmtk::components::multimesh {


NamedMultiMesh& MeshCollection::add_mesh(NamedMultiMesh m)
NamedMultiMesh& MeshCollection::add_mesh(NamedMultiMesh&& m)
{
auto mptr = std::make_unique<NamedMultiMesh>(std::move(m));
auto [it, did] = m_meshes.emplace(mptr->root_name(), std::move(mptr));


return *it->second;
}

Expand Down Expand Up @@ -51,6 +52,7 @@

const NamedMultiMesh& MeshCollection::get_named_multimesh(const std::string_view& path) const
{
assert(!m_meshes.empty());
using namespace std;
#if defined(WMTK_ENABLED_CPP20)
std::ranges::view auto split = internal::split_path(path);
Expand All @@ -63,6 +65,19 @@
"assuming that is the right mesh");
return *m_meshes.begin()->second;
}
if (auto it = m_meshes.find(nmm_name); it == m_meshes.end()) {
std::vector<std::string_view> names;
std::transform(

Check warning on line 70 in components/multimesh/src/wmtk/components/multimesh/MeshCollection.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/MeshCollection.cpp#L69-L70

Added lines #L69 - L70 were not covered by tests
m_meshes.begin(),
m_meshes.end(),
std::back_inserter(names),
[](const auto& pr) { return pr.first; });
wmtk::logger().error(

Check warning on line 75 in components/multimesh/src/wmtk/components/multimesh/MeshCollection.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/MeshCollection.cpp#L74-L75

Added lines #L74 - L75 were not covered by tests
"Was unable to find root mesh name {} among {} names [{}] in MeshCollection",
nmm_name,
m_meshes.size(),
fmt::join(names, ","));
}

Check warning on line 80 in components/multimesh/src/wmtk/components/multimesh/MeshCollection.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/MeshCollection.cpp#L78-L80

Added lines #L78 - L80 were not covered by tests
return *m_meshes.at(nmm_name);
}
NamedMultiMesh& MeshCollection::get_named_multimesh(const std::string_view& path)
Expand All @@ -80,7 +95,12 @@
"assuming that is the right mesh");
return *m_meshes.begin()->second;
}
return *m_meshes.at(nmm_name);
try {
return *m_meshes.at(nmm_name);
} catch (const std::runtime_error& e) {
wmtk::logger().warn("Failed to find mesh named {} in mesh list. Path was ", nmm_name, path);
throw e;
}

Check warning on line 103 in components/multimesh/src/wmtk/components/multimesh/MeshCollection.cpp

View check run for this annotation

Codecov / codecov/patch

components/multimesh/src/wmtk/components/multimesh/MeshCollection.cpp#L100-L103

Added lines #L100 - L103 were not covered by tests
}
std::map<std::string, const Mesh&> MeshCollection::all_meshes() const
// std::map<std::string, std::shared_ptr<const Mesh>> MeshCollection::all_meshes() const
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class InputOptions;
class MeshCollection
{
public:
NamedMultiMesh& add_mesh(NamedMultiMesh o);
NamedMultiMesh& add_mesh(NamedMultiMesh&& o);
template <typename... Args>
NamedMultiMesh& emplace_mesh(Args&&... args)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,12 @@ auto NamedMultiMesh::get_id(const std::string_view& path) const -> std::vector<i
Node const* cur_mesh = m_name_root.get();
assert(*split.begin() == cur_mesh->name || *split.begin() == "");
for (const auto& token : std::ranges::views::drop(split, 1)) {
// try {
int64_t index = cur_mesh->m_child_indexer.at(std::string(token));
//} catch(const std::runtime_error& e) {
// wmtk::logger().warn("Failed to find mesh named {} in mesh list. Path was ", nmm_name,
// path); throw e;
//}
indices.emplace_back(index);
cur_mesh = cur_mesh->m_children[index].get();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,22 @@ class NamedMultiMesh
{
public:
NamedMultiMesh();
explicit NamedMultiMesh(Mesh& m, const std::string& root_name);
NamedMultiMesh(Mesh& m, const std::string_view& root_name);
explicit NamedMultiMesh(Mesh& m, const nlohmann::json& root_name);

// Explicit constructors to remove ambiguities between string_view and json constructors
explicit NamedMultiMesh(Mesh& m, const std::string& root_name);
template <size_t N>
explicit NamedMultiMesh(Mesh& m, const char name[N])
: NamedMultiMesh(m, std::string_view(name))
{}
// NamedMultiMesh(NamedMultiMesh&&);
NamedMultiMesh(const NamedMultiMesh&);
~NamedMultiMesh();
// auto operator=(NamedMultiMesh&&) -> NamedMultiMesh&;
auto operator=(const NamedMultiMesh&) -> NamedMultiMesh&;

/// sets just the name of the root mesh, keeping child names the same
void set_name(const std::string_view& root_name = "");
void set_names(const nlohmann::json& js);
void set_root(Mesh& m);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#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
WMTK_NLOHMANN_JSON_SERIALIZE_ENUM(
AttributeType,
{
{AttributeType::Char, "char"},
{AttributeType::Double, "double"},
{AttributeType::Int64, "int"},
{AttributeType::Rational, "rational"},
})
} // namespace wmtk::attribute

namespace wmtk::components::multimesh::utils {
auto AttributeDescription::operator<=>(const AttributeDescription&) const -> std::strong_ordering =

Check warning on line 19 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#L19

Added line #L19 was not covered by tests
default;
auto AttributeDescription::operator==(const AttributeDescription&) const -> bool = default;

namespace {
NLOHMANN_JSON_SERIALIZE_ENUM(
PrimitiveType,
{
{PrimitiveType::Vertex, 0},
{PrimitiveType::Edge, 1},
{PrimitiveType::Triangle, 2},
{PrimitiveType::Tetrahedron, 3},
})
} // namespace
WMTK_NLOHMANN_JSON_FRIEND_TO_JSON_PROTOTYPE(AttributeDescription)
{
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)
{
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"];
}
}

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

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

} // namespace wmtk::components::multimesh::utils
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#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
{
std::string path;
std::optional<uint8_t> dimension;
std::optional<attribute::AttributeType> type;


AttributeDescription() = default;
AttributeDescription(const AttributeDescription&) = default;
AttributeDescription(AttributeDescription&&) = default;
AttributeDescription& operator=(const AttributeDescription&) = default;
AttributeDescription& operator=(AttributeDescription&&) = default;
~AttributeDescription() = default;

AttributeDescription(
const std::string_view& p,
const std::optional<uint8_t>& dim,
const std::optional<attribute::AttributeType>& t)
: path(p)
, dimension(dim)
, type(t)
{}

explicit AttributeDescription(
const std::string_view& p,
const std::optional<PrimitiveType>& pt,
const std::optional<attribute::AttributeType>& t)
: AttributeDescription(
p,
pt.has_value() ? std::optional<uint8_t>{wmtk::get_primitive_type_id(pt.value())}
: std::optional<uint8_t>{},
t)
{}


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

auto operator<=>(const AttributeDescription&) const -> std::strong_ordering;
auto operator==(const AttributeDescription&) const -> bool;


WMTK_NLOHMANN_JSON_FRIEND_DECLARATION(AttributeDescription)
};
} // namespace wmtk::components::multimesh::utils
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

#include "attribute_ambiguous_error.hpp"
#include <fmt/format.h>
#include <fmt/ranges.h>
#include <algorithm>
#include <iterator>
#include "named_error_text.hpp"
namespace wmtk::components::multimesh::utils::detail {

std::string attribute_ambiguous_error::make_message(
const AttributeDescription& ad,
const std::vector<AttributeDescription>& possibilities)
{
std::vector<std::string> names;

std::string (*maker)(const AttributeDescription&) = make_named_error_string;
std::transform(possibilities.begin(), possibilities.end(), std::back_inserter(names), maker);
return fmt::format(
"Multiple options for an attribute {} found: [{}]",
make_named_error_string(ad),
fmt::join(names, ","));
}
} // namespace wmtk::components::multimesh::utils::detail
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#pragma once
#include "attribute_error.hpp"
namespace wmtk::components::multimesh::utils {
struct AttributeDescription;
}

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

class attribute_ambiguous_error : public attribute_error
{
public:
static std::string make_message(
const AttributeDescription& description,
const std::vector<AttributeDescription>& possibilities);
attribute_ambiguous_error(
const AttributeDescription& d,
const std::vector<AttributeDescription>& possibilities)
: attribute_error(make_message(d, possibilities), d)
{}
template <typename... Args>
static attribute_ambiguous_error make(
const std::vector<AttributeDescription>& possiblities,
Args&&... args)
{
return attribute_ambiguous_error(
AttributeDescription{std::forward<Args>(args)...},
possiblities);
}
};


} // namespace wmtk::components::multimesh::utils::detail
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once
#include <optional>
#include <stdexcept>
#include <wmtk/Primitive.hpp>
#include <wmtk/attribute/AttributeType.hpp>
#include "../AttributeDescription.hpp"

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

class attribute_error : public std::range_error
{
public:
template <typename... Args>
attribute_error(const std::string_view& message, Args&&... args)
: std::range_error(std::string(message))
, description(std::forward<Args>(args)...)
{}
AttributeDescription description;
};
} // namespace wmtk::components::multimesh::utils::detail
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "attribute_missing_error.hpp"
#include "named_error_text.hpp"
namespace wmtk::components::multimesh::utils::detail {

std::string attribute_missing_error::make_message(const AttributeDescription& ad)
{
return "Could not find attribute " + make_named_error_string(ad);
}
} // namespace wmtk::components::multimesh::utils::detail
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#pragma once
#include "attribute_error.hpp"
namespace wmtk::components::multimesh::utils {
struct AttributeDescription;
}

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

class attribute_missing_error : public attribute_error
{
public:
static std::string make_message(const AttributeDescription& description);
attribute_missing_error(const AttributeDescription& d)
: attribute_error(make_message(d), d)
{}
template <typename... Args>
static attribute_missing_error make(Args&&... args)
{
return attribute_missing_error(AttributeDescription{std::forward<Args>(args)...});
}
};


} // namespace wmtk::components::multimesh::utils::detail
Loading