//----------------------------------------------------------------------------- double HexahedronCell::volume(const MeshEntity& cell) const { if (cell.dim() != 2) { dolfin_error("HexahedronCell.cpp", "compute volume (area) of cell", "Illegal mesh entity"); } // Get mesh geometry const MeshGeometry& geometry = cell.mesh().geometry(); // Get the coordinates of the four vertices const unsigned int* vertices = cell.entities(0); const Point p0 = geometry.point(vertices[0]); const Point p1 = geometry.point(vertices[1]); const Point p2 = geometry.point(vertices[2]); const Point p3 = geometry.point(vertices[3]); const Point p4 = geometry.point(vertices[4]); const Point p5 = geometry.point(vertices[5]); dolfin_error("HexahedronCell.cpp", "compute volume of hexahedron", "Not implemented"); return 0.0; }
//----------------------------------------------------------------------------- double IntervalCell::volume(const MeshEntity& interval) const { // Check that we get an interval if (interval.dim() != 1) { dolfin_error("IntervalCell.cpp", "compute volume (length) of interval cell", "Illegal mesh entity, not an interval"); } // Get mesh geometry const MeshGeometry& geometry = interval.mesh().geometry(); // Get the coordinates of the two vertices const unsigned int* vertices = interval.entities(0); const double* x0 = geometry.x(vertices[0]); const double* x1 = geometry.x(vertices[1]); // Compute length of interval (line segment) double sum = 0.0; for (std::size_t i = 0; i < geometry.dim(); ++i) { const double dx = x1[i] - x0[i]; sum += dx*dx; } return std::sqrt(sum); }
//----------------------------------------------------------------------------- double QuadrilateralCell::volume(const MeshEntity& cell) const { if (cell.dim() != 2) { dolfin_error("QuadrilateralCell.cpp", "compute volume (area) of cell", "Illegal mesh entity"); } // Get mesh geometry const MeshGeometry& geometry = cell.mesh().geometry(); // Get the coordinates of the four vertices const unsigned int* vertices = cell.entities(0); const Point p0 = geometry.point(vertices[0]); const Point p1 = geometry.point(vertices[1]); const Point p2 = geometry.point(vertices[2]); const Point p3 = geometry.point(vertices[3]); if (geometry.dim() == 2) { const Point c = (p0 - p2).cross(p1 - p3); return 0.5 * c.norm(); } else dolfin_error("QuadrilateralCell.cpp", "compute volume of quadrilateral", "Only know how to compute volume in R^2"); // FIXME: could work in R^3 but need to check co-planarity return 0.0; }
//----------------------------------------------------------------------------- bool CollisionDetection::collides_interval_point(const MeshEntity& entity, const Point& point) { // Get coordinates const MeshGeometry& geometry = entity.mesh().geometry(); const unsigned int* vertices = entity.entities(0); return collides_interval_point(geometry.point(vertices[0]), geometry.point(vertices[1]), point); }
//----------------------------------------------------------------------------- bool CollisionDetection::collides_triangle_triangle(const MeshEntity& triangle_0, const MeshEntity& triangle_1) { dolfin_assert(triangle_0.mesh().topology().dim() == 2); dolfin_assert(triangle_1.mesh().topology().dim() == 2); // Get vertices as points const MeshGeometry& geometry_0 = triangle_0.mesh().geometry(); const unsigned int* vertices_0 = triangle_0.entities(0); const MeshGeometry& geometry_1 = triangle_1.mesh().geometry(); const unsigned int* vertices_1 = triangle_1.entities(0); return collides_triangle_triangle(geometry_0.point(vertices_0[0]), geometry_0.point(vertices_0[1]), geometry_0.point(vertices_0[2]), geometry_1.point(vertices_1[0]), geometry_1.point(vertices_1[1]), geometry_1.point(vertices_1[2])); }
//----------------------------------------------------------------------------- // High-level collision detection predicates //----------------------------------------------------------------------------- bool CollisionPredicates::collides(const MeshEntity& entity, const Point& point) { // Intersection is only implemented for simplex meshes if (!entity.mesh().type().is_simplex()) { dolfin_error("Cell.cpp", "intersect cell and point", "Intersection is only implemented for simplex meshes"); } // Get data const MeshGeometry& g = entity.mesh().geometry(); const unsigned int* v = entity.entities(0); const std::size_t tdim = entity.mesh().topology().dim(); const std::size_t gdim = entity.mesh().geometry().dim(); // Pick correct specialized implementation if (tdim == 1 && gdim == 1) return collides_segment_point_1d(g.point(v[0])[0], g.point(v[1])[0], point[0]); if (tdim == 1 && gdim == 2) return collides_segment_point_2d(g.point(v[0]), g.point(v[1]), point); if (tdim == 1 && gdim == 3) return collides_segment_point_3d(g.point(v[0]), g.point(v[1]), point); if (tdim == 2 && gdim == 2) return collides_triangle_point_2d(g.point(v[0]), g.point(v[1]), g.point(v[2]), point); if (tdim == 2 && gdim == 3) return collides_triangle_point_3d(g.point(v[0]), g.point(v[1]), g.point(v[2]), point); if (tdim == 3) return collides_tetrahedron_point_3d(g.point(v[0]), g.point(v[1]), g.point(v[2]), g.point(v[3]), point); dolfin_error("CollisionPredicates.cpp", "compute entity-point collision", "Not implemented for dimensions %d / %d", tdim, gdim); return false; }
//----------------------------------------------------------------------------- double TriangleCell::volume(const MeshEntity& triangle) const { // Check that we get a triangle if (triangle.dim() != 2) { dolfin_error("TriangleCell.cpp", "compute volume (area) of triangle cell", "Illegal mesh entity, not a triangle"); } // Get mesh geometry const MeshGeometry& geometry = triangle.mesh().geometry(); // Get the coordinates of the three vertices const unsigned int* vertices = triangle.entities(0); const double* x0 = geometry.x(vertices[0]); const double* x1 = geometry.x(vertices[1]); const double* x2 = geometry.x(vertices[2]); if (geometry.dim() == 2) { // Compute area of triangle embedded in R^2 double v2 = (x0[0]*x1[1] + x0[1]*x2[0] + x1[0]*x2[1]) - (x2[0]*x1[1] + x2[1]*x0[0] + x1[0]*x0[1]); // Formula for volume from http://mathworld.wolfram.com return 0.5 * std::abs(v2); } else if (geometry.dim() == 3) { // Compute area of triangle embedded in R^3 const double v0 = (x0[1]*x1[2] + x0[2]*x2[1] + x1[1]*x2[2]) - (x2[1]*x1[2] + x2[2]*x0[1] + x1[1]*x0[2]); const double v1 = (x0[2]*x1[0] + x0[0]*x2[2] + x1[2]*x2[0]) - (x2[2]*x1[0] + x2[0]*x0[2] + x1[2]*x0[0]); const double v2 = (x0[0]*x1[1] + x0[1]*x2[0] + x1[0]*x2[1]) - (x2[0]*x1[1] + x2[1]*x0[0] + x1[0]*x0[1]); // Formula for volume from http://mathworld.wolfram.com return 0.5*sqrt(v0*v0 + v1*v1 + v2*v2); } else { dolfin_error("TriangleCell.cpp", "compute volume of triangle", "Only know how to compute volume when embedded in R^2 or R^3"); } return 0.0; }
//----------------------------------------------------------------------------- bool CollisionDetection::collides_tetrahedron_triangle(const MeshEntity& tetrahedron, const MeshEntity& triangle) { dolfin_assert(tetrahedron.mesh().topology().dim() == 3); dolfin_assert(triangle.mesh().topology().dim() == 2); // Get the vertices of the tetrahedron as points const MeshGeometry& geometry_tet = tetrahedron.mesh().geometry(); const unsigned int* vertices_tet = tetrahedron.entities(0); // Get the vertices of the triangle as points const MeshGeometry& geometry_tri = triangle.mesh().geometry(); const unsigned int* vertices_tri = triangle.entities(0); return collides_tetrahedron_triangle(geometry_tet.point(vertices_tet[0]), geometry_tet.point(vertices_tet[1]), geometry_tet.point(vertices_tet[2]), geometry_tet.point(vertices_tet[3]), geometry_tri.point(vertices_tri[0]), geometry_tri.point(vertices_tri[1]), geometry_tri.point(vertices_tri[2])); }
//----------------------------------------------------------------------------- bool CollisionDetection::collides_interval_interval(const MeshEntity& interval_0, const MeshEntity& interval_1) { // Get coordinates const MeshGeometry& geometry_0 = interval_0.mesh().geometry(); const MeshGeometry& geometry_1 = interval_1.mesh().geometry(); const unsigned int* vertices_0 = interval_0.entities(0); const unsigned int* vertices_1 = interval_1.entities(0); const double x00 = geometry_0.point(vertices_0[0])[0]; const double x01 = geometry_0.point(vertices_0[1])[0]; const double x10 = geometry_1.point(vertices_1[0])[0]; const double x11 = geometry_1.point(vertices_1[1])[0]; const double a0 = std::min(x00, x01); const double b0 = std::max(x00, x01); const double a1 = std::min(x10, x11); const double b1 = std::max(x10, x11); // Check for collisions const double dx = std::min(b0 - a0, b1 - a1); const double eps = std::max(DOLFIN_EPS_LARGE, DOLFIN_EPS_LARGE*dx); return b1 > a0 - eps && a1 < b0 + eps; }
//----------------------------------------------------------------------------- bool CollisionDetection::collides_tetrahedron_point(const MeshEntity& tetrahedron, const Point& point) { dolfin_assert(tetrahedron.mesh().topology().dim() == 3); // Get the vertices as points const MeshGeometry& geometry = tetrahedron.mesh().geometry(); const unsigned int* vertices = tetrahedron.entities(0); return collides_tetrahedron_point(geometry.point(vertices[0]), geometry.point(vertices[1]), geometry.point(vertices[2]), geometry.point(vertices[3]), point); }
//----------------------------------------------------------------------------- bool CollisionDetection::collides_triangle_point(const MeshEntity& triangle, const Point& point) { dolfin_assert(triangle.mesh().topology().dim() == 2); const MeshGeometry& geometry = triangle.mesh().geometry(); const unsigned int* vertices = triangle.entities(0); if (triangle.mesh().geometry().dim() == 2) return collides_triangle_point_2d(geometry.point(vertices[0]), geometry.point(vertices[1]), geometry.point(vertices[2]), point); else return collides_triangle_point(geometry.point(vertices[0]), geometry.point(vertices[1]), geometry.point(vertices[2]), point); }
//----------------------------------------------------------------------------- double IntervalCell::volume(const MeshEntity& interval) const { // Check that we get an interval if (interval.dim() != 1) { dolfin_error("IntervalCell.cpp", "compute volume (length) of interval cell", "Illegal mesh entity, not an interval"); } // Get mesh geometry const MeshGeometry& geometry = interval.mesh().geometry(); // Get the coordinates of the two vertices const unsigned int* vertices = interval.entities(0); const Point x0 = geometry.point(vertices[0]); const Point x1 = geometry.point(vertices[1]); return x1.distance(x0); }
//----------------------------------------------------------------------------- double TriangleCell::diameter(const MeshEntity& triangle) const { // Check that we get a triangle if (triangle.dim() != 2) { dolfin_error("TriangleCell.cpp", "compute diameter of triangle cell", "Illegal mesh entity, not a triangle"); } // Get mesh geometry const MeshGeometry& geometry = triangle.mesh().geometry(); // Only know how to compute the diameter when embedded in R^2 or R^3 if (geometry.dim() != 2 && geometry.dim() != 3) dolfin_error("TriangleCell.cpp", "compute diameter of triangle", "Only know how to compute diameter when embedded in R^2 or R^3"); // Get the coordinates of the three vertices const unsigned int* vertices = triangle.entities(0); const Point p0 = geometry.point(vertices[0]); const Point p1 = geometry.point(vertices[1]); const Point p2 = geometry.point(vertices[2]); // FIXME: Assuming 3D coordinates, could be more efficient if // FIXME: if we assumed 2D coordinates in 2D // Compute side lengths const double a = p1.distance(p2); const double b = p0.distance(p2); const double c = p0.distance(p1); // Formula for diameter (2*circumradius) from http://mathworld.wolfram.com return 0.5*a*b*c / volume(triangle); }
//----------------------------------------------------------------------------- bool CollisionPredicates::collides(const MeshEntity& entity_0, const MeshEntity& entity_1) { // Intersection is only implemented for simplex meshes if (!entity_0.mesh().type().is_simplex() || !entity_1.mesh().type().is_simplex()) { dolfin_error("Cell.cpp", "intersect cell and point", "intersection is only implemented for simplex meshes"); } // Get data const MeshGeometry& g0 = entity_0.mesh().geometry(); const MeshGeometry& g1 = entity_1.mesh().geometry(); const unsigned int* v0 = entity_0.entities(0); const unsigned int* v1 = entity_1.entities(0); const std::size_t d0 = entity_0.dim(); const std::size_t d1 = entity_1.dim(); const std::size_t gdim = g0.dim(); dolfin_assert(gdim == g1.dim()); // Pick correct specialized implementation if (d0 == 1 && d1 == 1) { return collides_segment_segment(g0.point(v0[0]), g0.point(v0[1]), g1.point(v1[0]), g1.point(v1[1]), gdim); } if (d0 == 1 && d1 == 2) { return collides_triangle_segment(g1.point(v1[0]), g1.point(v1[1]), g1.point(v1[2]), g0.point(v0[0]), g0.point(v0[1]), gdim); } if (d0 == 2 && d1 == 1) { return collides_triangle_segment(g0.point(v0[0]), g0.point(v0[1]), g0.point(v0[2]), g1.point(v1[0]), g1.point(v1[1]), gdim); } if (d0 == 2 && d1 == 2) { return collides_triangle_triangle(g0.point(v0[0]), g0.point(v0[1]), g0.point(v0[2]), g1.point(v1[0]), g1.point(v1[1]), g1.point(v1[2]), gdim); } if (d0 == 2 && d1 == 3) { return collides_tetrahedron_triangle_3d(g1.point(v1[0]), g1.point(v1[1]), g1.point(v1[2]), g1.point(v1[3]), g0.point(v0[0]), g0.point(v0[1]), g0.point(v0[2])); } if (d0 == 3 && d1 == 2) { return collides_tetrahedron_triangle_3d(g0.point(v0[0]), g0.point(v0[1]), g0.point(v0[2]), g0.point(v0[3]), g1.point(v1[0]), g1.point(v1[1]), g1.point(v1[2])); } if (d0 == 3 && d1 == 3) { return collides_tetrahedron_tetrahedron_3d(g0.point(v0[0]), g0.point(v0[1]), g0.point(v0[2]), g0.point(v0[3]), g1.point(v1[0]), g1.point(v1[1]), g1.point(v1[2]), g1.point(v1[3])); } dolfin_error("CollisionPredicates.cpp", "compute entity-entity collision", "Not implemented for topological dimensions %d / %d and geometrical dimension %d", d0, d1, gdim); return false; }
//----------------------------------------------------------------------------- bool CollisionDetection::collides_tetrahedron_tetrahedron (const MeshEntity& tetrahedron_0, const MeshEntity& tetrahedron_1) { // This algorithm checks whether two tetrahedra intersect. // Algorithm and source code from Fabio Ganovelli, Federico Ponchio // and Claudio Rocchini: Fast Tetrahedron-Tetrahedron Overlap // Algorithm, Journal of Graphics Tools, 7(2), 2002. DOI: // 10.1080/10867651.2002.10487557. Source code available at // http://web.archive.org/web/20031130075955/http://www.acm.org/jgt/papers/GanovelliPonchioRocchini02/tet_a_tet.html dolfin_assert(tetrahedron_0.mesh().topology().dim() == 3); dolfin_assert(tetrahedron_1.mesh().topology().dim() == 3); // Get the vertices as points const MeshGeometry& geometry = tetrahedron_0.mesh().geometry(); const unsigned int* vertices = tetrahedron_0.entities(0); const MeshGeometry& geometry_q = tetrahedron_1.mesh().geometry(); const unsigned int* vertices_q = tetrahedron_1.entities(0); std::vector<Point> V1(4), V2(4); for (std::size_t i = 0; i < 4; ++i) { V1[i] = geometry.point(vertices[i]); V2[i] = geometry_q.point(vertices_q[i]); } // Get the vectors between V2 and V1[0] std::vector<Point> P_V1(4); for (std::size_t i = 0; i < 4; ++i) P_V1[i] = V2[i]-V1[0]; // Data structure for edges of V1 and V2 std::vector<Point> e_v1(5), e_v2(5); e_v1[0] = V1[1] - V1[0]; e_v1[1] = V1[2] - V1[0]; e_v1[2] = V1[3] - V1[0]; Point n = e_v1[1].cross(e_v1[0]); // Maybe flip normal. Normal should be outward. if (n.dot(e_v1[2]) > 0) n *= -1; std::vector<int> masks(4); std::vector<std::vector<double>> Coord_1(4, std::vector<double>(4)); if (separating_plane_face_A_1(P_V1, n, Coord_1[0], masks[0])) return false; n = e_v1[0].cross(e_v1[2]); // Maybe flip normal if (n.dot(e_v1[1]) > 0) n *= -1; if (separating_plane_face_A_1(P_V1, n, Coord_1[1], masks[1])) return false; if (separating_plane_edge_A(Coord_1, masks, 0, 1)) return false; n = e_v1[2].cross(e_v1[1]); // Maybe flip normal if (n.dot(e_v1[0]) > 0) n *= -1; if (separating_plane_face_A_1(P_V1, n, Coord_1[2], masks[2])) return false; if (separating_plane_edge_A(Coord_1, masks, 0, 2)) return false; if (separating_plane_edge_A(Coord_1, masks, 1,2)) return false; e_v1[4] = V1[3] - V1[1]; e_v1[3] = V1[2] - V1[1]; n = e_v1[3].cross(e_v1[4]); // Maybe flip normal. Note the < since e_v1[0]=v1-v0. if (n.dot(e_v1[0]) < 0) n *= -1; if (separating_plane_face_A_2(V1, V2, n, Coord_1[3], masks[3])) return false; if (separating_plane_edge_A(Coord_1, masks, 0, 3)) return false; if (separating_plane_edge_A(Coord_1, masks, 1, 3)) return false; if (separating_plane_edge_A(Coord_1, masks, 2, 3)) return false; if ((masks[0] | masks[1] | masks[2] | masks[3] )!= 15) return true; // From now on, if there is a separating plane, it is parallel to a // face of b. std::vector<Point> P_V2(4); for (std::size_t i = 0; i < 4; ++i) P_V2[i] = V1[i] - V2[0]; e_v2[0] = V2[1] - V2[0]; e_v2[1] = V2[2] - V2[0]; e_v2[2] = V2[3] - V2[0]; n = e_v2[1].cross(e_v2[0]); // Maybe flip normal if (n.dot(e_v2[2])>0) n *= -1; if (separating_plane_face_B_1(P_V2, n)) return false; n=e_v2[0].cross(e_v2[2]); // Maybe flip normal if (n.dot(e_v2[1]) > 0) n *= -1; if (separating_plane_face_B_1(P_V2, n)) return false; n = e_v2[2].cross(e_v2[1]); // Maybe flip normal if (n.dot(e_v2[0]) > 0) n *= -1; if (separating_plane_face_B_1(P_V2, n)) return false; e_v2[4] = V2[3] - V2[1]; e_v2[3] = V2[2] - V2[1]; n = e_v2[3].cross(e_v2[4]); // Maybe flip normal. Note the < since e_v2[0] = V2[1] - V2[0]. if (n.dot(e_v2[0]) < 0) n *= -1; if (separating_plane_face_B_2(V1, V2, n)) return false; return true; }
//----------------------------------------------------------------------------- void SubMesh::init(const Mesh& mesh, const std::vector<std::size_t>& sub_domains, std::size_t sub_domain) { // Open mesh for editing MeshEditor editor; const std::size_t D = mesh.topology().dim(); editor.open(*this, mesh.type().cell_type(), D, mesh.geometry().dim()); // Build set of cells that are in sub-mesh std::vector<bool> parent_cell_in_subdomain(mesh.num_cells(), false); std::set<std::size_t> submesh_cells; for (CellIterator cell(mesh); !cell.end(); ++cell) { if (sub_domains[cell->index()] == sub_domain) { parent_cell_in_subdomain[cell->index()] = true; submesh_cells.insert(cell->index()); } } // Map from parent vertex index to submesh vertex index std::map<std::size_t, std::size_t> parent_to_submesh_vertex_indices; // Map from submesh cell to parent cell std::vector<std::size_t> submesh_cell_parent_indices; submesh_cell_parent_indices.reserve(submesh_cells.size()); // Vector from parent cell index to submesh cell index std::vector<std::size_t> parent_to_submesh_cell_indices(mesh.num_cells(), 0); // Add sub-mesh cells editor.init_cells_global(submesh_cells.size(), submesh_cells.size()); std::size_t current_cell = 0; std::size_t current_vertex = 0; for (std::set<std::size_t>::iterator cell_it = submesh_cells.begin(); cell_it != submesh_cells.end(); ++cell_it) { // Data structure to hold new vertex indices for cell std::vector<std::size_t> cell_vertices; // Create cell Cell cell(mesh, *cell_it); // Iterate over cell vertices for (VertexIterator vertex(cell); !vertex.end(); ++vertex) { const std::size_t parent_vertex_index = vertex->index(); // Look for parent vertex in map std::map<std::size_t, std::size_t>::iterator vertex_it = parent_to_submesh_vertex_indices.find(parent_vertex_index); // If vertex has been inserted, get new index, otherwise // increment and insert std::size_t submesh_vertex_index = 0; if (vertex_it != parent_to_submesh_vertex_indices.end()) submesh_vertex_index = vertex_it->second; else { submesh_vertex_index = current_vertex++; parent_to_submesh_vertex_indices[parent_vertex_index] = submesh_vertex_index; } // Add vertex to list of cell vertices (new indexing) cell_vertices.push_back(submesh_vertex_index); } // Add parent cell index to list submesh_cell_parent_indices.push_back(cell.index()); // Store parent cell -> submesh cell indices parent_to_submesh_cell_indices[cell.index()] = current_cell; // Add cell to mesh editor.add_cell(current_cell++, cell_vertices); } // Vector to hold submesh vertex -> parent vertex std::vector<std::size_t> parent_vertex_indices; parent_vertex_indices.resize(parent_to_submesh_vertex_indices.size()); // Initialise mesh editor editor.init_vertices_global(parent_to_submesh_vertex_indices.size(), parent_to_submesh_vertex_indices.size()); // Add vertices for (std::map<std::size_t, std::size_t>::iterator it = parent_to_submesh_vertex_indices.begin(); it != parent_to_submesh_vertex_indices.end(); ++it) { Vertex vertex(mesh, it->first); if (MPI::size(mesh.mpi_comm()) > 1) error("SubMesh::init not working in parallel"); // FIXME: Get global vertex index editor.add_vertex(it->second, vertex.point()); parent_vertex_indices[it->second] = it->first; } // Close editor editor.close(); // Build submesh-to-parent map for vertices std::vector<std::size_t>& parent_vertex_indices_mf = data().create_array("parent_vertex_indices", 0); parent_vertex_indices_mf.resize(num_vertices()); for (std::map<std::size_t, std::size_t>::iterator it = parent_to_submesh_vertex_indices.begin(); it != parent_to_submesh_vertex_indices.end(); ++it) { parent_vertex_indices_mf[it->second] = it->first; } // Build submesh-to-parent map for cells std::vector<std::size_t>& parent_cell_indices = data().create_array("parent_cell_indices", D); parent_cell_indices.resize(num_cells()); current_cell = 0; for (std::vector<std::size_t>::iterator it = submesh_cell_parent_indices.begin(); it != submesh_cell_parent_indices.end(); ++it) { parent_cell_indices[current_cell++] = *it; } // Initialise present MeshDomain const MeshDomains& parent_domains = mesh.domains(); this->domains().init(parent_domains.max_dim()); // Collect MeshValueCollections from parent mesh for (std::size_t dim_t = 0; dim_t <= parent_domains.max_dim(); dim_t++) { // If parent mesh does not has a data for dim_t if (parent_domains.num_marked(dim_t) == 0) continue; // Initialise connectivity mesh.init(dim_t, D); // FIXME: Can avoid building this map for cell and vertices // Build map from submesh entity (parent vertex list) -> (submesh index) mesh.init(dim_t); std::map<std::vector<std::size_t>, std::size_t> entity_map; for (MeshEntityIterator e(*this, dim_t); !e.end(); ++e) { // Build list of entity vertex indices and sort std::vector<std::size_t> vertex_list; for (VertexIterator v(*e); !v.end(); ++v) vertex_list.push_back(parent_vertex_indices[v->index()]); std::sort(vertex_list.begin(), vertex_list.end()); entity_map.insert(std::make_pair(vertex_list, e->index())); } // Get submesh marker map std::map<std::size_t, std::size_t>& submesh_markers = this->domains().markers(dim_t); // Get values map from parent MeshValueCollection const std::map<std::size_t, std::size_t>& parent_markers = parent_domains.markers(dim_t); // Iterate over all parents marker values std::map<std::size_t, std::size_t>::const_iterator itt; for (itt = parent_markers.begin(); itt != parent_markers.end(); itt++) { // Create parent entity const MeshEntity parent_entity(mesh, dim_t, itt->first); // FIXME: Need to check all attached cells std::size_t parent_cell_index = std::numeric_limits<std::size_t>::max(); if (dim_t == D) { parent_cell_index = itt->first; } else { // Get first parent cell index attached to parent entity for (std::size_t i = 0; i < parent_entity.num_entities(D); ++i) { if (sub_domains[parent_entity.entities(D)[i]] == sub_domain) { parent_cell_index = parent_entity.entities(D)[i]; break; } } } // Check if the cell is included in the submesh if (sub_domains[parent_cell_index] == sub_domain) { // Map markers from parent mesh to submesh if (dim_t == D) { // Get submesh cell index const std::size_t submesh_cell_index = parent_to_submesh_cell_indices[parent_cell_index]; submesh_markers[submesh_cell_index] = itt->second; } else { std::vector<std::size_t> parent_vertex_list; for (VertexIterator v(parent_entity); !v.end(); ++v) parent_vertex_list.push_back(v->index()); std::sort(parent_vertex_list.begin(), parent_vertex_list.end()); // Get submesh entity index std::map<std::vector<std::size_t>, std::size_t>::const_iterator submesh_it = entity_map.find(parent_vertex_list); dolfin_assert(submesh_it != entity_map.end()); submesh_markers[submesh_it->second] = itt->second; } } } } }