Wildmeshing Toolkit
get_attribute.cpp
Go to the documentation of this file.
1 
2 #include "get_attribute.hpp"
3 #include <ranges>
4 #include <wmtk/Mesh.hpp>
6 #include "..//MeshCollection.hpp"
7 #include "../NamedMultiMesh.hpp"
12 #include "get_attribute.hpp"
13 #include "wmtk/utils/Logger.hpp"
14 
16 namespace detail {
17 // turns an attribute path mesh.path/attrname to mesh.path attrname
18 // std::array<std::string_view, 2>
19 auto decompose_attribute_path(std::string_view attribute_path)
20 {
21 #if defined(WMTK_ENABLED_CPP20)
22  using namespace std;
23  auto tmp = std::ranges::views::split(attribute_path, "/"sv) |
24  std::views::transform([](const auto& r) noexcept -> std::string_view {
25  return std::string_view(r.begin(), r.end());
26  });
27 
28  std::array<std::string_view, 2> ret;
29  std::ranges::copy(tmp, ret.begin());
30  if (ret[1].empty()) {
31  std::swap(ret[0], ret[1]);
32  }
33  return ret;
34 #else
35 
36  std::array<std::string, 2> ret;
37  std::vector<std::string> tmp;
38  if (attribute_path.empty()) {
39  tmp.emplace_back("");
40  tmp.emplace_back("");
41 
42  } else {
43  std::string v = std::string(attribute_path);
44  std::istringstream iss(v);
45  std::string token;
46  if (v.size() > 0 && v[0] == '/') {
47  tmp.emplace_back("");
48  }
49  while (std::getline(iss, token, '/')) {
50  if (!token.empty()) tmp.emplace_back(token);
51  }
52  // at most 2 tokens are allowed
53  assert(tmp.size() <= 2);
54  if (tmp.size() == 1) {
55  tmp = {"", tmp[0]};
56  }
57  }
58  return std::array<std::string, 2>{{tmp[0], tmp[1]}};
59 #endif
60 }
61 
62 // std::array<std::string_view, 2>
64 {
65  return decompose_attribute_path(description.path);
66 }
67 template <typename T>
69 get_attribute(const Mesh& mesh, const std::string_view& name, PrimitiveType pt)
70 {
71  if (mesh.has_attribute<T>(std::string(name), pt)) {
72  return mesh.get_attribute_handle<T>(std::string(name), pt);
73  } else {
75  std::string(name),
77  wmtk::attribute ::attribute_type_enum_from_type<T>());
78  }
79 }
80 
82  const Mesh& mesh,
83  const std::string_view& name,
84  PrimitiveType pt,
86 {
88  switch (type) {
89 #define ENTRY(TYPE) \
90  case TYPE: \
91  return get_attribute<wmtk::attribute::type_from_attribute_type_enum_t<TYPE>>( \
92  mesh, \
93  name, \
94  pt);
95  ENTRY(AT::Char);
96  ENTRY(AT::Double);
97  ENTRY(AT::Int64);
99 #undef ENTRY
100  default: assert(false);
101  }
102  return {};
103 }
105  const Mesh& mesh,
106  const std::string_view& name,
107  std::optional<PrimitiveType> pt,
108  std::optional<wmtk::attribute::AttributeType> type)
109 {
111  // This order matches wmtk::components::utils::get_attributes
112  constexpr static std::array<AT, 4> types{{AT::Char, AT::Int64, AT::Double, AT::Rational}};
113  // constexpr static std::array<AT, 4> types{{AT::Int64, AT::Double, AT::Char, AT::Rational}};
114  std::vector<AttributeDescription> possibilities;
116  auto add_option = [&](PrimitiveType prim, AT t) {
117  ret = get_attribute(mesh, name, prim, t);
118 
119  uint8_t dimension = wmtk::get_primitive_type_id(prim);
120  possibilities.emplace_back(AttributeDescription{name, dimension, t});
121  };
122  if (pt.has_value() && type.has_value()) {
123  add_option(pt.value(), type.value());
124 
125  } else if (pt.has_value()) {
126  for (AT at : types) {
127  try {
128  add_option(pt.value(), at);
129  } catch (const attribute_missing_error& e) {
130  continue;
131  }
132  }
133  } else if (type.has_value()) {
135  try {
136  add_option(p, type.value());
137  } catch (const attribute_missing_error& e) {
138  continue;
139  }
140  }
141  } else {
142  for (AT at : types) {
144  try {
145  add_option(p, at);
146  } catch (const attribute_missing_error& e) {
147  continue;
148  }
149  }
150  }
151  }
152 
153 
154  if (possibilities.empty()) {
155  throw attribute_missing_error::make(name, pt, type);
156  } else if (possibilities.size() > 1) {
157  throw attribute_ambiguous_error::make(possibilities, name,pt,type);
158  }
159 
160  assert(ret.is_valid());
161  return ret;
162 }
163 } // namespace detail
164 
166  const NamedMultiMesh& mesh,
167  const AttributeDescription& description)
168 {
169  auto [mesh_path, attribute_name] = detail::decompose_attribute_path(description);
170  return detail::get_attribute(
171  mesh.get_mesh(mesh_path),
172  attribute_name,
173  description.primitive_type(),
174  description.type);
175 }
177  const MeshCollection& mesh,
178  const AttributeDescription& description)
179 {
180  auto [mesh_path, attribute_name] = detail::decompose_attribute_path(description);
181 
182  const Mesh& nmm = mesh.get_mesh(mesh_path);
183  return detail::get_attribute(
184  nmm,
185  attribute_name,
186  description.primitive_type(),
187  description.type);
188 }
189 
191  const Mesh& mesh,
192  const AttributeDescription& description)
193 {
194  auto [mesh_path, attribute_name] = detail::decompose_attribute_path(description);
195  return detail::get_attribute(
196  mesh,
197  attribute_name,
198  description.primitive_type(),
199  description.type);
200 }
201 
202 } // namespace wmtk::components::multimesh::utils
attribute::MeshAttributeHandle get_attribute_handle(const std::string &name, const PrimitiveType ptype) const
Definition: Mesh.hpp:917
bool has_attribute(const std::string &name, const PrimitiveType ptype) const
Definition: Mesh.hpp:937
PrimitiveType top_simplex_type() const
Definition: Mesh.hpp:996
const Mesh & get_mesh(const std::string_view &path) const
Mesh & get_mesh(const std::string_view &path) const
static attribute_ambiguous_error make(const std::vector< AttributeDescription > &possiblities, Args &&... args)
#define ENTRY(TYPE)
Definition: autodiff.h:995
auto decompose_attribute_path(std::string_view attribute_path)
wmtk::attribute::MeshAttributeHandle get_attribute(const Mesh &mesh, const std::string_view &name, PrimitiveType pt)
std::vector< PrimitiveType > primitive_below(PrimitiveType pt, bool lower_to_upper)
constexpr int8_t get_primitive_type_id(PrimitiveType t)
Get a unique integer id corresponding to each primitive type.