39 std::vector<tensor<double, d>>
gather(
const mfem::Vector& coordinates, mfem::Array<int> ids)
41 int num_vertices = coordinates.Size() / d;
42 std::vector<tensor<double, d>> x(std::size_t(ids.Size()));
43 for (
int v = 0; v < ids.Size(); v++) {
44 for (
int j = 0; j < d; j++) {
45 x[uint32_t(v)][j] = coordinates[j * num_vertices + ids[v]];
52 static Domain domain_of_vertices(
const mfem::Mesh& mesh, std::function<
bool(tensor<double, d>)> predicate)
54 assert(mesh.SpaceDimension() == d);
56 Domain output{mesh, 0 };
60 mfem::Vector vertices;
61 mesh.GetVertices(vertices);
64 int num_vertices = mesh.GetNV();
65 for (
int i = 0; i < num_vertices; i++) {
67 for (
int j = 0; j < d; j++) {
68 x[j] = vertices[j * num_vertices + i];
72 output.vertex_ids_.push_back(i);
81 return domain_of_vertices(mesh, func);
86 return domain_of_vertices(mesh, func);
92 template <
int d,
typename T>
93 static Domain domain_of_edges(
const mfem::Mesh& mesh, std::function<T> predicate)
95 assert(mesh.SpaceDimension() == d);
101 mfem::Vector vertices;
102 mesh.GetVertices(vertices);
104 mfem::Array<int> edge_id_to_bdr_id;
106 edge_id_to_bdr_id = mesh.GetFaceToBdrElMap();
109 int num_edges = mesh.GetNEdges();
110 for (
int i = 0; i < num_edges; i++) {
111 mfem::Array<int> vertex_ids;
112 mesh.GetEdgeVertices(i, vertex_ids);
114 auto x = gather<d>(vertices, vertex_ids);
116 if constexpr (d == 2) {
117 int bdr_id = edge_id_to_bdr_id[i];
118 int attr = (bdr_id > 0) ? mesh.GetBdrAttribute(bdr_id) : -1;
119 if (predicate(x, attr)) {
120 output.edge_ids_.push_back(i);
124 output.edge_ids_.push_back(i);
134 return domain_of_edges<2>(mesh, func);
139 return domain_of_edges<3>(mesh, func);
146 static Domain domain_of_faces(
const mfem::Mesh& mesh,
149 assert(mesh.SpaceDimension() == d);
155 mfem::Vector vertices;
156 mesh.GetVertices(vertices);
158 mfem::Array<int> face_id_to_bdr_id;
160 face_id_to_bdr_id = mesh.GetFaceToBdrElMap();
166 num_faces = mesh.GetNE();
168 num_faces = mesh.GetNumFaces();
174 for (
int i = 0; i < num_faces; i++) {
175 mfem::Array<int> vertex_ids;
177 if (mesh.Dimension() == 2) {
178 mesh.GetElementVertices(i, vertex_ids);
180 mesh.GetFaceVertices(i, vertex_ids);
183 auto x = gather<d>(vertices, vertex_ids);
187 attr = mesh.GetAttribute(i);
189 int bdr_id = face_id_to_bdr_id[i];
190 attr = (bdr_id >= 0) ? mesh.GetBdrAttribute(bdr_id) : -1;
193 if (predicate(x, attr)) {
195 output.tri_ids_.push_back(tri_id);
198 output.quad_ids_.push_back(quad_id);
215 return domain_of_faces(mesh, func);
220 return domain_of_faces(mesh, func);
227 static Domain domain_of_elems(
const mfem::Mesh& mesh,
230 assert(mesh.SpaceDimension() == d);
232 Domain output{mesh, mesh.SpaceDimension() };
236 mfem::Vector vertices;
237 mesh.GetVertices(vertices);
245 int num_elems = mesh.GetNE();
246 for (
int i = 0; i < num_elems; i++) {
247 mfem::Array<int> vertex_ids;
248 mesh.GetElementVertices(i, vertex_ids);
250 auto x = gather<d>(vertices, vertex_ids);
252 bool add = predicate(x, mesh.GetAttribute(i));
257 output.tri_ids_.push_back(tri_id);
262 if constexpr (d == 2) {
264 output.quad_ids_.push_back(quad_id);
268 if constexpr (d == 3) {
270 output.tet_ids_.push_back(tet_id);
277 output.hex_ids_.push_back(hex_id);
282 SLIC_ERROR(
"unsupported element type");
292 return domain_of_elems<2>(mesh, func);
297 return domain_of_elems<3>(mesh, func);
304 static Domain domain_of_boundary_elems(
const mfem::Mesh& mesh,
307 assert(mesh.SpaceDimension() == d);
309 Domain output{mesh, d - 1, Domain::Type::BoundaryElements};
311 mfem::Array<int> face_id_to_bdr_id = mesh.GetFaceToBdrElMap();
315 mfem::Vector vertices;
316 mesh.GetVertices(vertices);
323 for (
int f = 0; f < mesh.GetNumFaces(); f++) {
325 if (mesh.GetFaceInformation(f).IsInterior())
continue;
327 auto geom = mesh.GetFaceGeometry(f);
329 mfem::Array<int> vertex_ids;
330 mesh.GetFaceVertices(f, vertex_ids);
332 auto x = gather<d>(vertices, vertex_ids);
334 int bdr_id = face_id_to_bdr_id[f];
335 int attr = (bdr_id >= 0) ? mesh.GetBdrAttribute(bdr_id) : -1;
337 bool add = predicate(x, attr);
340 case mfem::Geometry::SEGMENT:
342 output.edge_ids_.push_back(edge_id);
346 case mfem::Geometry::TRIANGLE:
348 output.tri_ids_.push_back(tri_id);
352 case mfem::Geometry::SQUARE:
354 output.quad_ids_.push_back(quad_id);
359 SLIC_ERROR(
"unsupported element type");
369 return domain_of_boundary_elems<2>(mesh, func);
374 return domain_of_boundary_elems<3>(mesh, func);
384 Domain output{mesh, mesh.SpaceDimension() };
392 int num_elems = mesh.GetNE();
393 for (
int i = 0; i < num_elems; i++) {
394 auto geom = mesh.GetElementGeometry(i);
397 case mfem::Geometry::TRIANGLE:
398 output.tri_ids_.push_back(tri_id++);
400 case mfem::Geometry::SQUARE:
401 output.quad_ids_.push_back(quad_id++);
403 case mfem::Geometry::TETRAHEDRON:
404 output.tet_ids_.push_back(tet_id++);
406 case mfem::Geometry::CUBE:
407 output.hex_ids_.push_back(hex_id++);
410 SLIC_ERROR(
"unsupported element type");
420 Domain output{mesh, mesh.SpaceDimension() - 1, Domain::Type::BoundaryElements};
426 for (
int f = 0; f < mesh.GetNumFaces(); f++) {
428 if (mesh.GetFaceInformation(f).IsInterior())
continue;
430 auto geom = mesh.GetFaceGeometry(f);
433 case mfem::Geometry::SEGMENT:
434 output.edge_ids_.push_back(edge_id++);
436 case mfem::Geometry::TRIANGLE:
437 output.tri_ids_.push_back(tri_id++);
439 case mfem::Geometry::SQUARE:
440 output.quad_ids_.push_back(quad_id++);
443 SLIC_ERROR(
"unsupported element type");
452 using c_iter = std::vector<int>::const_iterator;
453 using b_iter = std::back_insert_iterator<std::vector<int>>;
454 using set_op = std::function<b_iter(c_iter, c_iter, c_iter, c_iter, b_iter)>;
456 set_op union_op = std::set_union<c_iter, c_iter, b_iter>;
457 set_op intersection_op = std::set_intersection<c_iter, c_iter, b_iter>;
458 set_op difference_op = std::set_difference<c_iter, c_iter, b_iter>;
462 std::vector<int>
set_operation(set_op op,
const std::vector<int>& a,
const std::vector<int>& b)
464 std::vector<int> output;
465 op(a.begin(), a.end(), b.begin(), b.end(), back_inserter(output));
477 if (output.dim_ == 0) {
478 output.vertex_ids_ =
set_operation(op, a.vertex_ids_, b.vertex_ids_);
481 if (output.dim_ == 1) {
482 output.edge_ids_ =
set_operation(op, a.edge_ids_, b.edge_ids_);
485 if (output.dim_ == 2) {
487 output.quad_ids_ =
set_operation(op, a.quad_ids_, b.quad_ids_);
490 if (output.dim_ == 3) {
many of the functions in this file amount to extracting element indices from an mfem::Mesh like
Accelerator functionality.
Domain EntireBoundary(const mfem::Mesh &mesh)
constructs a domain from all the boundary elements in a mesh
Domain operator-(const Domain &a, const Domain &b)
create a new domain that is the set difference of a and b
std::vector< tensor< double, d > > gather(const mfem::Vector &coordinates, mfem::Array< int > ids)
gather vertex coordinates for a list of vertices
Domain operator&(const Domain &a, const Domain &b)
create a new domain that is the intersection of a and b
Domain operator|(const Domain &a, const Domain &b)
create a new domain that is the union of a and b
Domain EntireDomain(const mfem::Mesh &mesh)
constructs a domain from all the elements in a mesh
std::vector< int > set_operation(set_op op, const std::vector< int > &a, const std::vector< int > &b)
return a std::vector that is the result of applying (a op b)
a class for representing a geometric region that can be used for integration
static Domain ofFaces(const mfem::Mesh &mesh, std::function< bool(std::vector< vec2 >, int)> func)
create a domain from some subset of the faces in an mfem::Mesh
static Domain ofBoundaryElements(const mfem::Mesh &mesh, std::function< bool(std::vector< vec2 >, int)> func)
create a domain from some subset of the boundary elements (spatial dim == geometry dim + 1) in an mfe...
static Domain ofVertices(const mfem::Mesh &mesh, std::function< bool(vec2)> func)
create a domain from some subset of the vertices in an mfem::Mesh
int dim_
the geometric dimension of the domain
const mfem::Mesh & mesh_
the underyling mesh for this domain
static Domain ofElements(const mfem::Mesh &mesh, std::function< bool(std::vector< vec2 >, int)> func)
create a domain from some subset of the elements (spatial dim == geometry dim) in an mfem::Mesh
static Domain ofEdges(const mfem::Mesh &mesh, std::function< bool(std::vector< vec2 >, int)> func)
create a domain from some subset of the edges in an mfem::Mesh
Arbitrary-rank tensor class.