Skip to content

Commit 80a24a1

Browse files
committed
Oversized commit. Adds num_vertices. Implements MOAB ID<-->index mapping using intrinsic IDs
1 parent 841b1c8 commit 80a24a1

8 files changed

Lines changed: 141 additions & 95 deletions

File tree

include/xdg/libmesh/mesh_manager.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ class LibMeshManager : public MeshManager {
8080
}
8181
}
8282

83+
int num_vertices() const override {
84+
return mesh()->n_nodes();
85+
}
86+
8387
int num_volume_elements(MeshID volume) const override {
8488
return get_volume_elements(volume).size();
8589
}

include/xdg/mesh_manager_interface.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ class MeshManager {
6767
const Position& u) const;
6868

6969
// Mesh
70+
virtual int num_vertices() const = 0;
71+
7072
virtual int num_volume_elements(MeshID volume) const = 0;
7173

7274
virtual int num_volume_elements() const;

include/xdg/moab/direct_access.h

Lines changed: 20 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -47,35 +47,13 @@ class MBDirectAccess {
4747

4848
//! \brief Determine the index of an element in the managed data
4949
inline size_t element_index(EntityHandle element) {
50-
size_t element_index = 0;
51-
auto fe = element_data_.first_elements.begin();
52-
while(true) {
53-
if (element - fe->first < fe->second) { break; }
54-
element_index += fe->second;
55-
fe++;
56-
if (fe == element_data_.first_elements.end()) {
57-
throw std::runtime_error("Element not found in MBDirectAccess::element_index");
58-
}
59-
}
60-
element_index += element - fe->first;
61-
return element_index;
50+
return element_data_.entity_range.index(element);
6251
}
6352

6453
//! \brief Determine the element handle of an element based on its index in
6554
//! the managed data
6655
inline EntityHandle element_handle(size_t index) {
67-
size_t running_index = 0;
68-
auto fe = element_data_.first_elements.begin();
69-
while(true) {
70-
if (index < running_index + fe->second) {
71-
return fe->first + (index - running_index);
72-
}
73-
running_index += fe->second;
74-
fe++;
75-
if (fe == element_data_.first_elements.end()) {
76-
throw std::runtime_error("Index out of range in MBDirectAccess::element_handle");
77-
}
78-
}
56+
return element_data_.entity_range[index];
7957
}
8058

8159
//! \brief Get the coordinates of a triangle as XDG Vertices
@@ -102,33 +80,11 @@ class MBDirectAccess {
10280
}
10381

10482
int vertex_index(EntityHandle vertex) {
105-
int vertex_index = 0;
106-
auto fe = vertex_data_.first_vertices.begin();
107-
while(true) {
108-
if (vertex - fe->first < fe->second) { break; }
109-
vertex_index += fe->second;
110-
fe++;
111-
if (fe == vertex_data_.first_vertices.end()) {
112-
throw std::runtime_error("Vertex not found in MBDirectAccess::vertex_index");
113-
}
114-
}
115-
vertex_index += vertex - fe->first;
116-
return vertex_index;
83+
return vertex_data_.vertex_range.index(vertex);
11784
}
11885

11986
EntityHandle vertex_handle(int vertex_index) {
120-
int running_index = 0;
121-
auto fe = vertex_data_.first_vertices.begin();
122-
while(true) {
123-
if (vertex_index < running_index + fe->second) {
124-
return fe->first + (vertex_index - running_index);
125-
}
126-
running_index += fe->second;
127-
fe++;
128-
if (fe == vertex_data_.first_vertices.end()) {
129-
throw std::runtime_error("Index out of range in MBDirectAccess::vertex_handle");
130-
}
131-
}
87+
return vertex_data_.vertex_range[vertex_index];
13288
}
13389

13490
//! \brief Get the adjacent element
@@ -233,33 +189,33 @@ class MBDirectAccess {
233189
int element_stride {-1}; //!< Number of vertices used by each element
234190
std::vector<std::pair<EntityHandle, size_t>> first_elements; //!< Pairs of first element and length pairs for contiguous blocks of memory
235191
std::vector<const EntityHandle*> vconn; //!< Storage array(s) for the connectivity array
192+
moab::Range entity_range; //!< Range of entities managed
236193

237194
void setup(Interface * mbi) {
238195
ErrorCode rval;
239196

240197
// setup face connectivity data
241-
Range faces;
242-
rval = mbi->get_entities_by_type(0, entity_type, faces, true);
243-
MB_CHK_SET_ERR_CONT(rval, "Failed to get all elements of dimension 2 (faces)");
244-
num_entities = faces.size();
198+
rval = mbi->get_entities_by_type(0, entity_type, entity_range, true);
199+
MB_CHK_SET_ERR_CONT(rval, "Failed to get all elements for the given entity type");
200+
num_entities = entity_range.size();
245201

246202
// only supporting triangle elements for now
247-
if (!faces.all_of_type(entity_type)) { throw std::runtime_error("Not all 2D elements are triangles"); }
203+
if (!entity_range.all_of_type(entity_type)) { throw std::runtime_error("Not all 2D elements are triangles"); }
248204

249-
moab::Range::iterator faces_it = faces.begin();
250-
while(faces_it != faces.end()) {
205+
moab::Range::iterator entity_it = entity_range.begin();
206+
while(entity_it != entity_range.end()) {
251207
// set connectivity pointer, element stride and the number of elements
252208
EntityHandle* conntmp;
253209
int n_elements;
254-
rval = mbi->connect_iterate(faces_it, faces.end(), conntmp, element_stride, n_elements);
210+
rval = mbi->connect_iterate(entity_it, entity_range.end(), conntmp, element_stride, n_elements);
255211
MB_CHK_SET_ERR_CONT(rval, "Failed to get direct access to triangle elements");
256212

257213
// set const pointers for the connectivity array and add first element/length pair to the set of first elements
258214
vconn.push_back(conntmp);
259-
first_elements.push_back({*faces_it, n_elements});
215+
first_elements.push_back({*entity_it, n_elements});
260216

261217
// move iterator forward by the number of triangles in this contiguous memory block
262-
faces_it += n_elements;
218+
entity_it += n_elements;
263219
}
264220
}
265221

@@ -295,19 +251,18 @@ class MBDirectAccess {
295251
void setup(Interface* mbi) {
296252
ErrorCode rval;
297253
// setup vertices
298-
Range verts;
299-
rval = mbi->get_entities_by_dimension(0, 0, verts, true);
254+
rval = mbi->get_entities_by_dimension(0, 0, vertex_range, true);
300255
MB_CHK_SET_ERR_CONT(rval, "Failed to get all elements of dimension 0 (vertices)");
301-
num_vertices = verts.size();
256+
num_vertices = vertex_range.size();
302257

303-
moab::Range::iterator verts_it = verts.begin();
304-
while (verts_it != verts.end()) {
258+
moab::Range::iterator verts_it = vertex_range.begin();
259+
while (verts_it != vertex_range.end()) {
305260
// set vertex coordinate pointers
306261
double* xtmp;
307262
double* ytmp;
308263
double* ztmp;
309264
int n_vertices;
310-
rval = mbi->coords_iterate(verts_it, verts.end(), xtmp, ytmp, ztmp, n_vertices);
265+
rval = mbi->coords_iterate(verts_it, vertex_range.end(), xtmp, ytmp, ztmp, n_vertices);
311266
MB_CHK_SET_ERR_CONT(rval, "Failed to get direct access to vertex elements");
312267

313268
// add the vertex coordinate arrays to their corresponding vector of array pointers
@@ -351,6 +306,7 @@ class MBDirectAccess {
351306
std::vector<const double*> ty; //!< Storage array(s) for vertex y coordinates
352307
std::vector<const double*> tz; //!< Storage array(s) for vertex z coordinates
353308
std::vector<std::pair<EntityHandle, size_t>> first_vertices; //!< Pairs of first vertex and length pairs for contiguous blocks of memory
309+
moab::Range vertex_range; //!< Range of entities managed
354310
};
355311

356312
ConnectivityData face_data_;

include/xdg/moab/mesh_manager.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ class MOABMeshManager : public MeshManager {
5454
void add_surface_to_volume(MeshID volume, MeshID surface, Sense sense, bool overwrite=false) override;
5555

5656
// Mesh
57+
int num_vertices() const override {
58+
return this->mb_direct()->n_vertices();
59+
}
60+
5761
int num_volume_elements(MeshID volume) const override;
5862

5963
int num_volume_elements() const override;
@@ -83,7 +87,7 @@ class MOABMeshManager : public MeshManager {
8387
inline MeshID element_id(size_t element_idx) const override {
8488
// MOAB element IDs start at one and may not be contiguous,
8589
// so we need to map from index to ID
86-
return tag_data<MeshID>(global_id_tag_, mb_direct()->element_handle(element_idx));
90+
return moab_interface()->id_from_handle(mb_direct()->element_handle(element_idx));
8791
}
8892

8993
inline int element_index(MeshID element) const override {
@@ -96,7 +100,7 @@ class MOABMeshManager : public MeshManager {
96100

97101
inline MeshID vertex_id(size_t vertex_idx) const override {
98102
moab::EntityHandle vertex_handle = mb_direct()->vertex_handle(vertex_idx);
99-
return tag_data<MeshID>(global_id_tag_, vertex_handle);
103+
return moab_interface()->id_from_handle(vertex_handle);
100104
}
101105

102106
inline int vertex_index(MeshID vertex) const override {

tests/mesh_mock.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ class MeshMock : public MeshManager {
5656
return -1;
5757
}
5858

59+
virtual int num_vertices() const override {
60+
return vertices_.size();
61+
}
62+
5963
virtual int num_volume_elements(MeshID volume) const override {
6064
if (!volumetric_elements_) return 0;
6165
return 12;

tests/test_files

Submodule test_files updated 1 file

tests/test_libmesh.cpp

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,8 @@ TEST_CASE("LibMesh Element ID and Index Mapping")
388388
REQUIRE(element_index == static_cast<int>(i));
389389
}
390390

391-
size_t num_vertices = static_cast<LibMeshManager*>(mesh_manager.get())->mesh()->n_nodes();
391+
size_t num_vertices = mesh_manager->num_vertices();
392+
REQUIRE(num_vertices == 2067);
392393
for (size_t i = 0; i < num_vertices; i++) {
393394
MeshID vertex_id = mesh_manager->vertex_id(i);
394395
int vertex_index = mesh_manager->vertex_index(vertex_id);
@@ -398,12 +399,12 @@ TEST_CASE("LibMesh Element ID and Index Mapping")
398399

399400
// test mapping for non-contiguous IDs via manual modification
400401
{
401-
// now create a new mesh manager
402-
std::unique_ptr<LibMeshManager> mesh_manager2 {std::make_unique<LibMeshManager>()};
403-
mesh_manager2->load_file("jezebel.exo");
402+
// now create a new mesh manager (create explicitly so we can modify the mesh before init)
403+
std::unique_ptr<LibMeshManager> mesh_manager {std::make_unique<LibMeshManager>()};
404+
mesh_manager->load_file("jezebel.exo");
404405

405406
// tweak some of the element IDs to create gaps
406-
auto* mesh = mesh_manager2->mesh();
407+
auto* mesh = mesh_manager->mesh();
407408
int next_id = 0;
408409
std::vector<MeshID> modified_element_ids;
409410
for (auto* elem : mesh->active_element_ptr_range()) {
@@ -437,38 +438,38 @@ TEST_CASE("LibMesh Element ID and Index Mapping")
437438
mesh->allow_renumbering(false);
438439

439440
// now initialize the mesh manager
440-
mesh_manager2->init();
441-
REQUIRE(mesh_manager2->num_volume_elements() == 10333);
441+
mesh_manager->init();
442+
REQUIRE(mesh_manager->num_volume_elements() == 10333);
442443

443444
// check element ID to index mapping
444445
int expected_index = 0;
445-
for (const auto* elem : mesh_manager2->mesh()->active_element_ptr_range()) {
446+
for (const auto* elem : mesh_manager->mesh()->active_element_ptr_range()) {
446447
MeshID element_id = elem->id();
447-
int element_index = mesh_manager2->element_index(element_id);
448+
int element_index = mesh_manager->element_index(element_id);
448449
REQUIRE(element_index == expected_index);
449450
expected_index++;
450451
}
451452

452453
// check node ID to index mapping
453454
expected_index = 0;
454-
for (const auto* node : mesh_manager2->mesh()->node_ptr_range()) {
455+
for (const auto* node : mesh_manager->mesh()->node_ptr_range()) {
455456
MeshID vertex_id = node->id();
456-
int vertex_index = mesh_manager2->vertex_index(vertex_id);
457+
int vertex_index = mesh_manager->vertex_index(vertex_id);
457458
REQUIRE(vertex_index == expected_index);
458459
expected_index++;
459460
}
460461

461462
// check index to element ID mapping
462-
size_t num_elements = mesh_manager2->num_volume_elements();
463+
size_t num_elements = mesh_manager->num_volume_elements();
463464
for (size_t i = 0; i < num_elements; i++) {
464-
MeshID element_id = mesh_manager2->element_id(i);
465+
MeshID element_id = mesh_manager->element_id(i);
465466
REQUIRE(element_id == modified_element_ids[i]);
466467
}
467468

468469
// check index to vertex ID mapping
469-
size_t num_vertices = mesh_manager2->mesh()->n_nodes();
470+
size_t num_vertices = mesh_manager->mesh()->n_nodes();
470471
for (size_t i = 0; i < num_vertices; i++) {
471-
MeshID vertex_id = mesh_manager2->vertex_id(i);
472+
MeshID vertex_id = mesh_manager->vertex_id(i);
472473
REQUIRE(vertex_id == modified_vertex_ids[i]);
473474
}
474475
}

tests/test_moab.cpp

Lines changed: 88 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -282,20 +282,95 @@ TEST_CASE("TEST MOAB Find Element Method")
282282

283283
TEST_CASE("MOAB Element ID and Index Mapping")
284284
{
285-
std::shared_ptr<XDG> xdg = XDG::create(MeshLibrary::MOAB);
286-
REQUIRE(xdg->mesh_manager()->mesh_library() == MeshLibrary::MOAB);
287-
const auto& mesh_manager = xdg->mesh_manager();
288-
mesh_manager->load_file("jezebel.h5m");
289-
mesh_manager->init();
285+
// test mapping for contiguous MOAB IDs using jezebel model
286+
{
287+
std::shared_ptr<XDG> xdg = XDG::create(MeshLibrary::MOAB);
288+
REQUIRE(xdg->mesh_manager()->mesh_library() == MeshLibrary::MOAB);
289+
const auto& mesh_manager = xdg->mesh_manager();
290+
mesh_manager->load_file("jezebel.h5m");
291+
mesh_manager->init();
292+
293+
size_t num_elements = mesh_manager->num_volume_elements();
294+
REQUIRE(num_elements == 10333);
295+
296+
for (size_t idx = 0; idx < num_elements; ++idx) {
297+
MeshID element_id = mesh_manager->element_id(idx);
298+
// MOAB element IDs start at 1 and, for this model, are contiguous
299+
REQUIRE(element_id == idx + 1);
300+
int mapped_idx = mesh_manager->element_index(element_id);
301+
REQUIRE(mapped_idx == static_cast<int>(idx));
302+
}
290303

291-
size_t num_elements = mesh_manager->num_volume_elements();
292-
REQUIRE(num_elements == 10333);
304+
size_t num_vertices = mesh_manager->num_vertices();
305+
REQUIRE(num_vertices == 2067);
306+
for (size_t idx = 0; idx < num_vertices; ++idx) {
307+
MeshID vertex_id = mesh_manager->vertex_id(idx);
308+
// MOAB vertex IDs start at 1 and, for this model, are contiguous
309+
REQUIRE(vertex_id == idx + 1);
310+
int mapped_idx = mesh_manager->vertex_index(vertex_id);
311+
REQUIRE(mapped_idx == static_cast<int>(idx));
312+
}
313+
}
314+
315+
// test mapping for non-contiguous MOAB IDs via modification
316+
{
317+
std::shared_ptr<MOABMeshManager> mesh_manager = std::make_shared<MOABMeshManager>();
318+
mesh_manager->load_file("jezebel.h5m");
319+
320+
moab::Interface* mbi = mesh_manager->moab_interface();
321+
322+
// create gaps in the intrinsic ID space by deleteing some elements
323+
moab::Range elem_range;
324+
mbi->get_entities_by_type(0, moab::MBTET, elem_range);
325+
int next_id = 0;
326+
std::vector<MeshID> modified_ids;
327+
for (const auto& elem : elem_range) {
328+
if (next_id % 100 == 0) {
329+
mbi->delete_entities(&elem, 1);
330+
next_id++;
331+
continue;
332+
}
333+
next_id ++;
334+
modified_ids.push_back(mbi->id_from_handle(elem));
335+
}
336+
337+
mesh_manager->init();
338+
339+
size_t num_elements = mesh_manager->num_volume_elements();
340+
REQUIRE(num_elements == modified_ids.size());
341+
for (size_t idx = 0; idx < num_elements; ++idx) {
342+
MeshID expected_id = modified_ids[idx];
343+
MeshID element_id = mesh_manager->element_id(idx);
344+
REQUIRE(element_id == expected_id);
345+
int mapped_idx = mesh_manager->element_index(element_id);
346+
REQUIRE(mapped_idx == static_cast<int>(idx));
347+
}
293348

294-
for (size_t idx = 0; idx < num_elements; ++idx) {
295-
MeshID element_id = mesh_manager->element_id(idx);
296-
// MOAB element IDs start at 1 and, for this model, are contiguous
297-
REQUIRE(element_id == idx + 1);
298-
int mapped_idx = mesh_manager->element_index(element_id);
299-
REQUIRE(mapped_idx == static_cast<int>(idx));
349+
// // modify the vertex global IDs to be non-contiguous
350+
// next_id = 0;
351+
// std::vector<MeshID> modified_vertex_ids;
352+
// moab::Range vertex_range;
353+
// mbi->get_entities_by_type(0, moab::MBVERTEX, vertex_range);
354+
// for (const auto& vertex : vertex_range) {
355+
// if (next_id % 50 == 0) {
356+
// mbi->delete_entities(&vertex, 1);
357+
// next_id++;
358+
// continue;
359+
// }
360+
// next_id++;
361+
// }
362+
363+
// // reset the direct access manager to update vertex data
364+
// mesh_manager->mb_direct()->update();
365+
366+
// size_t num_vertices = mesh_manager->num_vertices();
367+
// REQUIRE(num_vertices == modified_vertex_ids.size());
368+
// for (size_t idx = 0; idx < num_vertices; ++idx) {
369+
// MeshID expected_id = modified_vertex_ids[idx];
370+
// MeshID vertex_id = mesh_manager->vertex_id(idx);
371+
// REQUIRE(vertex_id == expected_id);
372+
// int mapped_idx = mesh_manager->vertex_index(vertex_id);
373+
// REQUIRE(mapped_idx == static_cast<int>(idx));
374+
// }
300375
}
301376
}

0 commit comments

Comments
 (0)