Mesh build_mesh(const std::vector<unsigned int>& cells, const std::vector<double>& vertices, int dim) { // vertices and cells are flattened unsigned int vlen = vertices.size() / dim; unsigned int clen = cells.size() / (dim + 1); Mesh mesh; MeshEditor editor; editor.open(mesh, dim, dim); editor.init_vertices(vlen); editor.init_cells(clen); if (dim==3) { for (int i=0; i<vlen; i++) editor.add_vertex(i, vertices[3*i], vertices[3*i+1], vertices[3*i+2]); for (int i=0; i<clen; i++) editor.add_cell(i, cells[4*i], cells[4*i+1], cells[4*i+2], cells[4*i+3]); } else { for (int i=0; i<vlen; i++) editor.add_vertex(i, vertices[2*i], vertices[2*i+1]); for (int i=0; i<clen; i++) editor.add_cell(i, cells[3*i], cells[3*i+1], cells[3*i+2]); } editor.close(); return mesh; }
int main(int argc, char** argv) { using namespace Eigen; using EigMat = SparseMatrix<double>; using EigVec = VectorXd; EigMat A(6,6); for(int i=0;i<6;++i) A.insert(i, i) = 1.0/i; SimplicialLLT<EigMat> solver(A); EigVec b(6); b << 1,2,3,4,5,6; EigVec X = solver.solve(b); cout << X << endl; ArgExtracter ae(argc, argv); init_glut(argc, argv); init_gl(); me.init(); register_console_funcs(&me); glutMainLoop(); return 0; }
//----------------------------------------------------------------------------- void TriangleCell::refine_cell(Cell& cell, MeshEditor& editor, std::size_t& current_cell) const { // Get vertices and edges const unsigned int* v = cell.entities(0); const unsigned int* e = cell.entities(1); dolfin_assert(v); dolfin_assert(e); // Get offset for new vertex indices const std::size_t offset = cell.mesh().num_vertices(); // Compute indices for the six new vertices const std::size_t v0 = v[0]; const std::size_t v1 = v[1]; const std::size_t v2 = v[2]; const std::size_t e0 = offset + e[find_edge(0, cell)]; const std::size_t e1 = offset + e[find_edge(1, cell)]; const std::size_t e2 = offset + e[find_edge(2, cell)]; // Create four new cells std::vector<std::vector<std::size_t>> cells(4, std::vector<std::size_t>(3)); cells[0][0] = v0; cells[0][1] = e2; cells[0][2] = e1; cells[1][0] = v1; cells[1][1] = e0; cells[1][2] = e2; cells[2][0] = v2; cells[2][1] = e1; cells[2][2] = e0; cells[3][0] = e0; cells[3][1] = e1; cells[3][2] = e2; // Add cells std::vector<std::vector<std::size_t>>::const_iterator _cell; for (_cell = cells.begin(); _cell != cells.end(); ++_cell) editor.add_cell(current_cell++, *_cell); }
void mouse(int button, int state, int x, int y) { Vec2i pos(x,WINY-y); if (state==GLUT_DOWN) { if (button==GLUT_LEFT_BUTTON && glutGetModifiers() == 0) me.grab_ball(ROTATE_ACTION,pos); else if (button==GLUT_LEFT_BUTTON && glutGetModifiers() == GLUT_ACTIVE_CTRL) me.select_vertex(pos); else if (button==GLUT_MIDDLE_BUTTON || glutGetModifiers() == GLUT_ACTIVE_CTRL) me.grab_ball(ZOOM_ACTION,pos); else if (button==GLUT_RIGHT_BUTTON || glutGetModifiers() == GLUT_ACTIVE_ALT) me.grab_ball(PAN_ACTION,pos); } else if (state==GLUT_UP) me.release_ball(); }
void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); me.display(); glutSwapBuffers(); }
//----------------------------------------------------------------------------- void dolfin::p_refine(Mesh& refined_mesh, const Mesh& mesh) { MeshEditor editor; if (mesh.geometry().degree() != 1) { dolfin_error("refine.cpp", "increase polynomial degree of mesh", "Currently only linear -> quadratic is supported"); } const CellType::Type cell_type = mesh.type().cell_type(); if (cell_type != CellType::Type::triangle and cell_type != CellType::Type::tetrahedron and cell_type != CellType::Type::interval) { dolfin_error("refine.cpp", "increase polynomial degree of mesh", "Unsupported cell type"); } const std::size_t tdim = mesh.topology().dim(); const std::size_t gdim = mesh.geometry().dim(); editor.open(refined_mesh, cell_type, tdim, gdim, 2); // Copy over mesh editor.init_vertices_global(mesh.num_entities(0), mesh.num_entities_global(0)); for (VertexIterator v(mesh); !v.end(); ++v) editor.add_vertex(v->index(), v->point()); editor.init_cells_global(mesh.num_entities(tdim), mesh.num_entities_global(tdim)); std::vector<std::size_t> verts(tdim + 1); for (CellIterator c(mesh); !c.end(); ++c) { std::copy(c->entities(0), c->entities(0) + tdim + 1, verts.begin()); editor.add_cell(c->index(), verts); } // Initialise edges editor.init_entities(); // Add points at centres of edges for (EdgeIterator e(refined_mesh); !e.end(); ++e) editor.add_entity_point(1, 0, e->index(), e->midpoint()); editor.close(); }
void keyboard_spec(int key, int x, int y) { switch (key) { case GLUT_KEY_UP: me.key_up(); break; case GLUT_KEY_DOWN: me.key_down(); break; case GLUT_KEY_LEFT: me.key_left(); break; case GLUT_KEY_RIGHT: me.key_right(); break; case GLUT_KEY_HOME: me.key_home(); break; case GLUT_KEY_END: me.key_end(); break; default: break; } glutPostRedisplay(); }
//----------------------------------------------------------------------------- void IntervalCell::refine_cell(Cell& cell, MeshEditor& editor, std::size_t& current_cell) const { // Get vertices const unsigned int* v = cell.entities(0); dolfin_assert(v); // Get offset for new vertex indices const std::size_t offset = cell.mesh().num_vertices(); // Compute indices for the three new vertices const std::size_t v0 = v[0]; const std::size_t v1 = v[1]; const std::size_t e0 = offset + cell.index(); // Add the two new cells std::vector<std::size_t> new_cell(2); new_cell[0] = v0; new_cell[1] = e0; editor.add_cell(current_cell++, new_cell); new_cell[0] = e0; new_cell[1] = v1; editor.add_cell(current_cell++, new_cell); }
//----------------------------------------------------------------------------- UnitTriangleMesh::UnitTriangleMesh() : Mesh() { // Receive mesh according to parallel policy if (MPI::is_receiver(this->mpi_comm())) { MeshPartitioning::build_distributed_mesh(*this); return; } // Open mesh for editing MeshEditor editor; editor.open(*this, CellType::triangle, 2, 2); // Create vertices editor.init_vertices_global(3, 3); std::vector<double> x(2); x[0] = 0.0; x[1] = 0.0; editor.add_vertex(0, x); x[0] = 1.0; x[1] = 0.0; editor.add_vertex(1, x); x[0] = 0.0; x[1] = 1.0; editor.add_vertex(2, x); // Create cells editor.init_cells_global(1, 1); std::vector<std::size_t> cell_data(3); cell_data[0] = 0; cell_data[1] = 1; cell_data[2] = 2; editor.add_cell(0, cell_data); // Close mesh editor editor.close(); // Broadcast mesh according to parallel policy if (MPI::is_broadcaster(this->mpi_comm())) { MeshPartitioning::build_distributed_mesh(*this); return; } }
//----------------------------------------------------------------------------- void LocalMeshCoarsening::collapse_edge(Mesh& mesh, Edge& edge, Vertex& vertex_to_remove, MeshFunction<bool>& cell_to_remove, std::vector<int>& old2new_vertex, std::vector<int>& old2new_cell, MeshEditor& editor, std::size_t& current_cell) { const CellType& cell_type = mesh.type(); std::vector<std::size_t> cell_vertices(cell_type.num_entities(0)); std::size_t vert_slave = vertex_to_remove.index(); std::size_t vert_master = 0; const unsigned int* edge_vertex = edge.entities(0); if ( edge_vertex[0] == vert_slave ) vert_master = edge_vertex[1]; else if ( edge_vertex[1] == vert_slave ) vert_master = edge_vertex[0]; else dolfin_error("LocalMeshCoarsening.cpp", "collapse edge", "The node to delete and edge to collapse are not compatible"); for (CellIterator c(vertex_to_remove); !c.end(); ++c) { if ( cell_to_remove[*c] == false ) { std::size_t cv_idx = 0; for (VertexIterator v(*c); !v.end(); ++v) { if ( v->index() == vert_slave ) cell_vertices[cv_idx++] = old2new_vertex[vert_master]; else cell_vertices[cv_idx++] = old2new_vertex[v->index()]; } //cout << "adding new cell" << endl; editor.add_cell(current_cell++, cell_vertices); // Update cell map old2new_cell[c->index()] = current_cell - 1; } } }
//----------------------------------------------------------------------------- void DynamicMeshEditor::close(bool order) { dolfin_assert(_mesh); dolfin_assert(_cell_type); // Open default mesh editor MeshEditor editor; editor.open(*_mesh, _cell_type->cell_type(), _tdim, _gdim); // Set number of vertices const std::size_t num_vertices = vertex_coordinates.size()/_gdim; editor.init_vertices(num_vertices); // Set number of cells const std::size_t vertices_per_cell = _cell_type->num_vertices(_gdim); const std::size_t num_cells = cell_vertices.size()/vertices_per_cell; editor.init_cells(num_cells); // Add vertices std::vector<double> p(_gdim); for (std::size_t v = 0; v < num_vertices; v++) { const std::size_t offset = v*_gdim; for (std::size_t i = 0; i < _gdim; i++) p[i] = vertex_coordinates[offset + i]; editor.add_vertex(v, p); } // Add cells std::vector<std::size_t> vertices(vertices_per_cell); for (std::size_t c = 0; c < num_cells; c++) { const std::size_t offset = c*vertices_per_cell; for (std::size_t i = 0; i < vertices_per_cell; i++) vertices[i] = cell_vertices[offset + i]; editor.add_cell(c, vertices); } // Close editor editor.close(order); // Clear data clear(); }
//----------------------------------------------------------------------------- void ParallelRefinement::build_local(Mesh& new_mesh) const { MeshEditor ed; const std::size_t tdim = _mesh.topology().dim(); const std::size_t gdim = _mesh.geometry().dim(); dolfin_assert(new_vertex_coordinates.size()%gdim == 0); const std::size_t num_vertices = new_vertex_coordinates.size()/gdim; const std::size_t num_cell_vertices = tdim + 1; dolfin_assert(new_cell_topology.size()%num_cell_vertices == 0); const std::size_t num_cells = new_cell_topology.size()/num_cell_vertices; ed.open(new_mesh, tdim, gdim); ed.init_vertices(num_vertices); std::size_t i = 0; for (auto p = new_vertex_coordinates.begin(); p != new_vertex_coordinates.end(); p += gdim) { std::vector<double> vertex(p, p + gdim); ed.add_vertex(i, vertex); ++i; } ed.init_cells(num_cells); i = 0; std::vector<std::size_t> cell(num_cell_vertices); for (auto p = new_cell_topology.begin(); p != new_cell_topology.end(); p += num_cell_vertices) { std::copy(p, p + num_cell_vertices, cell.begin()); ed.add_cell(i, cell); ++i; } ed.close(); }
//----------------------------------------------------------------------------- void BoundaryComputation::compute_boundary(const Mesh& mesh, const std::string type, BoundaryMesh& boundary) { // We iterate over all facets in the mesh and check if they are on // the boundary. A facet is on the boundary if it is connected to // exactly one cell. log(TRACE, "Computing boundary mesh."); bool exterior = true; bool interior = true; if (type == "exterior") interior = false; else if (type == "interior") exterior = false; else if (type != "local") { dolfin_error("BoundaryComputation.cpp", "determine boundary mesh type", "Unknown boundary type (%d)", type.c_str()); } // Get my MPI process rank and number of MPI processes const std::size_t my_rank = MPI::rank(mesh.mpi_comm()); const std::size_t num_processes = MPI::size(mesh.mpi_comm()); // Open boundary mesh for editing const std::size_t D = mesh.topology().dim(); MeshEditor editor; editor.open(boundary, mesh.type().facet_type(), D - 1, mesh.geometry().dim()); // Generate facet - cell connectivity if not generated mesh.init(D - 1, D); // Temporary arrays for assignment of indices to vertices on the boundary std::map<std::size_t, std::size_t> boundary_vertices; // Map of index "owners" (process responsible for assigning global index) std::map< std::size_t, std::size_t > global_index_owner; // Shared vertices for full mesh // FIXME: const_cast const std::map<unsigned int, std::set<unsigned int>> & shared_vertices = const_cast<Mesh&>(mesh).topology().shared_entities(0); // Shared vertices for boundary mesh std::map<unsigned int, std::set<unsigned int>> shared_boundary_vertices; if (exterior) { // Extract shared vertices if vertex is identified as part of globally // exterior facet. std::vector<std::size_t> boundary_global_indices; for (std::map<unsigned int, std::set<unsigned int>>::const_iterator sv_it=shared_vertices.begin(); sv_it != shared_vertices.end(); ++sv_it) { std::size_t local_mesh_index = sv_it->first; Vertex v(mesh, local_mesh_index); for (FacetIterator f(v); !f.end(); ++f) { if (f->num_global_entities(D) == 1) { const std::size_t global_mesh_index = mesh.topology().global_indices(0)[local_mesh_index]; shared_boundary_vertices[local_mesh_index] = sv_it->second; boundary_global_indices.push_back(global_mesh_index); break; } } } // Distribute all shared boundary vertices std::vector<std::vector<std::size_t>> boundary_global_indices_all; MPI::all_gather(mesh.mpi_comm(), boundary_global_indices, boundary_global_indices_all); // Identify and clean up discrepancies between shared vertices of full mesh // and shared vertices of boundary mesh for (auto sbv_it = shared_boundary_vertices.begin(); sbv_it != shared_boundary_vertices.end(); ) { std::size_t local_mesh_index = sbv_it->first; const std::size_t global_mesh_index = mesh.topology().global_indices(0)[local_mesh_index]; // Check if this vertex is identified as boundary vertex on // other processes sharing this vertex std::set<unsigned int> &other_processes = sbv_it->second; for (auto op_it=other_processes.begin(); op_it != other_processes.end(); ) { // Check if vertex is identified as boundary vertex on process *op_it bool is_boundary_vertex = (std::find(boundary_global_indices_all[*op_it].begin(), boundary_global_indices_all[*op_it].end(), global_mesh_index) != boundary_global_indices_all[*op_it].end()); // Erase item if this is not identified as a boundary vertex // on process *op_it, and increment iterator if (!is_boundary_vertex) { // Erase item while carefully avoiding invalidating the // iterator: First increment it to get the next, valid // iterator, and then erase what it pointed to from // other_processes other_processes.erase(op_it++); } else ++op_it; } // Erase item from map if no other processes identify this // vertex as a boundary vertex, and increment iterator if (other_processes.size() == 0) { // Erase carefully as above shared_boundary_vertices.erase(sbv_it++); } else ++sbv_it; } } else { // If interior boundary, shared vertices are the same shared_boundary_vertices = shared_vertices; } // Determine boundary facet, count boundary vertices and facets, and // assign vertex indices std::size_t num_boundary_vertices = 0; std::size_t num_owned_vertices = 0; std::size_t num_boundary_cells = 0; MeshFunction<bool> boundary_facet(reference_to_no_delete_pointer(mesh), D - 1, false); for (FacetIterator f(mesh); !f.end(); ++f) { // Boundary facets are connected to exactly one cell if (f->num_entities(D) == 1) { const bool global_exterior_facet = (f->num_global_entities(D) == 1); if (global_exterior_facet && exterior) boundary_facet[*f] = true; else if (!global_exterior_facet && interior) boundary_facet[*f] = true; if (boundary_facet[*f]) { // Count boundary vertices and assign indices for (VertexIterator v(*f); !v.end(); ++v) { const std::size_t local_mesh_index = v->index(); if (boundary_vertices.find(local_mesh_index) == boundary_vertices.end()) { const std::size_t local_boundary_index = num_boundary_vertices; boundary_vertices[local_mesh_index] = local_boundary_index; // Determine "owner" of global_mesh_index std::size_t owner = my_rank; std::map<unsigned int, std::set<unsigned int>>::const_iterator other_processes_it = shared_boundary_vertices.find(local_mesh_index); if (other_processes_it != shared_boundary_vertices.end() && D > 1) { const std::set<unsigned int>& other_processes = other_processes_it->second; const std::size_t min_process = *std::min_element(other_processes.begin(), other_processes.end()); boundary.topology().shared_entities(0)[local_boundary_index] = other_processes; // FIXME: More sophisticated ownership determination if (min_process < owner) owner = min_process; } const std::size_t global_mesh_index = mesh.topology().global_indices(0)[local_mesh_index]; global_index_owner[global_mesh_index] = owner; // Update counts if (owner == my_rank) num_owned_vertices++; num_boundary_vertices++; } } // Count boundary cells (facets of the mesh) num_boundary_cells++; } } } // Initiate boundary topology /* boundary.topology().init(0, num_boundary_vertices, MPI::sum(mesh.mpi_comm(), num_owned_vertices)); boundary.topology().init(D - 1, num_boundary_cells, MPI::sum(mesh.mpi_comm(), num_boundary_cells)); */ // Specify number of vertices and cells editor.init_vertices_global(num_boundary_vertices, MPI::sum(mesh.mpi_comm(), num_owned_vertices)); editor.init_cells_global(num_boundary_cells, MPI::sum(mesh.mpi_comm(), num_boundary_cells)); // Write vertex map MeshFunction<std::size_t>& vertex_map = boundary.entity_map(0); if (num_boundary_vertices > 0) { vertex_map.init(reference_to_no_delete_pointer(boundary), 0, num_boundary_vertices); } std::map<std::size_t, std::size_t>::const_iterator it; for (it = boundary_vertices.begin(); it != boundary_vertices.end(); ++it) vertex_map[it->second] = it->first; // Get vertex ownership distribution, and find index to start global // numbering from std::vector<std::size_t> ownership_distribution(num_processes); MPI::all_gather(mesh.mpi_comm(), num_owned_vertices, ownership_distribution); std::size_t start_index = 0; for (std::size_t j = 0; j < my_rank; j++) start_index += ownership_distribution[j]; // Set global indices of owned vertices, request global indices for // vertices owned elsewhere std::map<std::size_t, std::size_t> global_indices; std::vector<std::vector<std::size_t>> request_global_indices(num_processes); std::size_t current_index = start_index; for (std::size_t local_boundary_index = 0; local_boundary_index<num_boundary_vertices; local_boundary_index++) { const std::size_t local_mesh_index = vertex_map[local_boundary_index]; const std::size_t global_mesh_index = mesh.topology().global_indices(0)[local_mesh_index]; const std::size_t owner = global_index_owner[global_mesh_index]; if (owner != my_rank) request_global_indices[owner].push_back(global_mesh_index); else global_indices[global_mesh_index] = current_index++; } // Send and receive requests from other processes std::vector<std::vector<std::size_t>> global_index_requests(num_processes); MPI::all_to_all(mesh.mpi_comm(), request_global_indices, global_index_requests); // Find response to requests of global indices std::vector<std::vector<std::size_t>> respond_global_indices(num_processes); for (std::size_t i = 0; i < num_processes; i++) { const std::size_t N = global_index_requests[i].size(); respond_global_indices[i].resize(N); for (std::size_t j = 0; j < N; j++) respond_global_indices[i][j] = global_indices[global_index_requests[i][j]]; } // Scatter responses back to requesting processes std::vector<std::vector<std::size_t>> global_index_responses(num_processes); MPI::all_to_all(mesh.mpi_comm(), respond_global_indices, global_index_responses); // Update global_indices for (std::size_t i = 0; i < num_processes; i++) { const std::size_t N = global_index_responses[i].size(); // Check that responses are the same size as the requests made dolfin_assert(global_index_responses[i].size() == request_global_indices[i].size()); for (std::size_t j = 0; j < N; j++) { const std::size_t global_mesh_index = request_global_indices[i][j]; const std::size_t global_boundary_index = global_index_responses[i][j]; global_indices[global_mesh_index] = global_boundary_index; } } // Create vertices for (std::size_t local_boundary_index = 0; local_boundary_index < num_boundary_vertices; local_boundary_index++) { const std::size_t local_mesh_index = vertex_map[local_boundary_index]; const std::size_t global_mesh_index = mesh.topology().global_indices(0)[local_mesh_index]; const std::size_t global_boundary_index = global_indices[global_mesh_index]; Vertex v(mesh, local_mesh_index); editor.add_vertex_global(local_boundary_index, global_boundary_index, v.point()); } // Find global index to start cell numbering from for current process std::vector<std::size_t> cell_distribution(num_processes); MPI::all_gather(mesh.mpi_comm(), num_boundary_cells, cell_distribution); std::size_t start_cell_index = 0; for (std::size_t i = 0; i < my_rank; i++) start_cell_index += cell_distribution[i]; // Create cells (facets) and map between boundary mesh cells and facets parent MeshFunction<std::size_t>& cell_map = boundary.entity_map(D - 1); if (num_boundary_cells > 0) { cell_map.init(reference_to_no_delete_pointer(boundary), D - 1, num_boundary_cells); } std::vector<std::size_t> cell(boundary.type().num_vertices(boundary.topology().dim())); std::size_t current_cell = 0; for (FacetIterator f(mesh); !f.end(); ++f) { if (boundary_facet[*f]) { // Compute new vertex numbers for cell const unsigned int* vertices = f->entities(0); for (std::size_t i = 0; i < cell.size(); i++) cell[i] = boundary_vertices[vertices[i]]; // Reorder vertices so facet is right-oriented w.r.t. facet // normal reorder(cell, *f); // Create mapping from boundary cell to mesh facet if requested if (!cell_map.empty()) cell_map[current_cell] = f->index(); // Add cell editor.add_cell(current_cell, start_cell_index+current_cell, cell); current_cell++; } } // Close mesh editor. Note the argument order=false to prevent // ordering from destroying the orientation of facets accomplished // by calling reorder() below. editor.close(false); }
//----------------------------------------------------------------------------- bool LocalMeshCoarsening::coarsen_cell(Mesh& mesh, Mesh& coarse_mesh, int cellid, std::vector<int>& old2new_vertex, std::vector<int>& old2new_cell, bool coarsen_boundary) { cout << "coarsen_cell: " << cellid << endl; cout << "num_cells: " << mesh.num_cells() << endl; const std::size_t num_vertices = mesh.size(0); const std::size_t num_cells = mesh.size(mesh.topology().dim()); auto _mesh = reference_to_no_delete_pointer(mesh); // Initialise forbidden vertices MeshFunction<bool> vertex_forbidden(_mesh); vertex_forbidden.init(0); for (VertexIterator v(mesh); !v.end(); ++v) vertex_forbidden[v->index()] = false; // Initialise boundary vertices MeshFunction<bool> vertex_boundary(_mesh); vertex_boundary.init(0); for (VertexIterator v(mesh); !v.end(); ++v) vertex_boundary[v->index()] = false; BoundaryMesh boundary(mesh, "exterior"); MeshFunction<std::size_t>& bnd_vertex_map = boundary.entity_map(0); for (VertexIterator v(boundary); !v.end(); ++v) vertex_boundary[bnd_vertex_map[v->index()]] = true; // If coarsen boundary is forbidden if (coarsen_boundary == false) { for (VertexIterator v(boundary); !v.end(); ++v) vertex_forbidden[bnd_vertex_map[v->index()]] = true; } // Initialise data for finding which vertex to remove bool _collapse_edge = false; const unsigned int* edge_vertex; std::size_t shortest_edge_index = 0; double lmin, l; std::size_t num_cells_to_remove = 0; // Get cell type const CellType& cell_type = mesh.type(); const Cell cell(mesh, cellid); MeshEditor editor; editor.open(coarse_mesh, cell_type.cell_type(), mesh.topology().dim(), mesh.geometry().dim()); MeshFunction<bool> cell_to_remove(_mesh); cell_to_remove.init(mesh.topology().dim()); for (CellIterator ci(mesh); !ci.end(); ++ci) cell_to_remove[ci->index()] = false; MeshFunction<bool> cell_to_regenerate(_mesh); cell_to_regenerate.init(mesh.topology().dim()); for (CellIterator ci(mesh); !ci.end(); ++ci) cell_to_regenerate[ci->index()] = false; // Find shortest edge of cell c _collapse_edge = false; lmin = 1.0e10*cell.diameter(); for (EdgeIterator e(cell); !e.end(); ++e) { edge_vertex = e->entities(0); if (!vertex_forbidden[edge_vertex[0]] || !vertex_forbidden[edge_vertex[1]]) { l = e->length(); if ( lmin > l ) { lmin = l; shortest_edge_index = e->index(); _collapse_edge = true; } } } Edge shortest_edge(mesh, shortest_edge_index); // Decide which vertex to remove std::size_t vert2remove_idx = 0; // If at least one vertex should be removed if ( _collapse_edge == true ) { edge_vertex = shortest_edge.entities(0); if(vertex_forbidden[edge_vertex[0]] && vertex_forbidden[edge_vertex[1]]) { // Both vertices are forbidden, cannot coarsen cout << "both vertices forbidden" << endl; editor.close(); return false; } if(vertex_forbidden[edge_vertex[0]] == true) vert2remove_idx = edge_vertex[1]; else if(vertex_forbidden[edge_vertex[1]] == true) vert2remove_idx = edge_vertex[0]; else if(vertex_boundary[edge_vertex[1]] == true && vertex_boundary[edge_vertex[0]] == false) vert2remove_idx = edge_vertex[0]; else if(vertex_boundary[edge_vertex[0]] == true && vertex_boundary[edge_vertex[1]] == false) vert2remove_idx = edge_vertex[1]; else if ( edge_vertex[0] > edge_vertex[1] ) vert2remove_idx = edge_vertex[0]; else vert2remove_idx = edge_vertex[1]; } else { // No vertices to remove, cannot coarsen cout << "all vertices forbidden" << endl; editor.close(); return false; } Vertex vertex_to_remove(mesh, vert2remove_idx); // Remove cells around edge num_cells_to_remove = 0; for (CellIterator cn(shortest_edge); !cn.end(); ++cn) { cell_to_remove[cn->index()] = true; num_cells_to_remove++; // Update cell map old2new_cell[cn->index()] = -1; } // Regenerate cells around vertex for (CellIterator cn(vertex_to_remove); !cn.end(); ++cn) { cell_to_regenerate[cn->index()] = true; // Update cell map (will be filled in with correct index) old2new_cell[cn->index()] = -1; } // Specify number of vertices and cells editor.init_vertices_global(num_vertices - 1, num_vertices - 1); editor.init_cells_global(num_cells - num_cells_to_remove, num_cells - num_cells_to_remove); cout << "Number of cells in old mesh: " << num_cells << "; to remove: " << num_cells_to_remove << endl; // Add old vertices std::size_t vertex = 0; for(VertexIterator v(mesh); !v.end(); ++v) { if(vertex_to_remove.index() == v->index()) old2new_vertex[v->index()] = -1; else { //cout << "adding old vertex at: " << v->point() << endl; old2new_vertex[v->index()] = vertex; editor.add_vertex(vertex, v->point()); vertex++; } } // Add old unrefined cells std::size_t cv_idx; std::size_t current_cell = 0; std::vector<std::size_t> cell_vertices(cell_type.num_entities(0)); for (CellIterator c(mesh); !c.end(); ++c) { if (cell_to_remove[*c] == false && cell_to_regenerate[*c] == false) { cv_idx = 0; for (VertexIterator v(*c); !v.end(); ++v) cell_vertices[cv_idx++] = old2new_vertex[v->index()]; //cout << "adding old cell" << endl; editor.add_cell(current_cell++, cell_vertices); // Update cell maps old2new_cell[c->index()] = current_cell - 1; } } // Add new cells. collapse_edge(mesh, shortest_edge, vertex_to_remove, cell_to_remove, old2new_vertex, old2new_cell, editor, current_cell); editor.close(); // Set volume tolerance. This parameter determines a quality criterion // for the new mesh: higher value indicates a sharper criterion. double vol_tol = 1.0e-3; bool mesh_ok = true; Cell removed_cell(mesh, cellid); // Check mesh quality (volume) for (CellIterator c(removed_cell); !c.end(); ++c) { std::size_t id = c->index(); int nid = old2new_cell[id]; if(nid != -1) { Cell cn(coarse_mesh, nid); double qm = cn.volume() / cn.diameter(); if(qm < vol_tol) { warning("Cell quality too low"); cout << "qm: " << qm << endl; mesh_ok = false; return mesh_ok; } } } // Checking for inverted cells for (CellIterator c(removed_cell); !c.end(); ++c) { std::size_t id = c->index(); int nid = old2new_cell[id]; if(nid != -1) { Cell cn(coarse_mesh, nid); if(c->orientation() != cn.orientation()) { cout << "cell orientation inverted" << endl; mesh_ok = false; return mesh_ok; } } } return mesh_ok; }
void keyboard(unsigned char key, int x, int y) { me.keyparse(key); glutPostRedisplay(); }
//----------------------------------------------------------------------------- void RectangleMesh::build(const Point& p0, const Point& p1, std::size_t nx, std::size_t ny, std::string diagonal) { // Receive mesh according to parallel policy if (MPI::is_receiver(this->mpi_comm())) { MeshPartitioning::build_distributed_mesh(*this); return; } // Check options if (diagonal != "left" && diagonal != "right" && diagonal != "right/left" && diagonal != "left/right" && diagonal != "crossed") { dolfin_error("RectangleMesh.cpp", "create rectangle", "Unknown mesh diagonal definition: allowed options are \"left\", \"right\", \"left/right\", \"right/left\" and \"crossed\""); } // Extract minimum and maximum coordinates const double x0 = std::min(p0.x(), p1.x()); const double x1 = std::max(p0.x(), p1.x()); const double y0 = std::min(p0.y(), p1.y()); const double y1 = std::max(p0.y(), p1.y()); const double a = x0; const double b = x1; const double c = y0; const double d = y1; if (std::abs(x0 - x1) < DOLFIN_EPS || std::abs(y0 - y1) < DOLFIN_EPS) { dolfin_error("Rectangle.cpp", "create rectangle", "Rectangle seems to have zero width, height or depth. Consider checking your dimensions"); } if (nx < 1 || ny < 1) { dolfin_error("RectangleMesh.cpp", "create rectangle", "Rectangle has non-positive number of vertices in some dimension: number of vertices must be at least 1 in each dimension"); } rename("mesh", "Mesh of the unit square (a,b) x (c,d)"); // Open mesh for editing MeshEditor editor; editor.open(*this, CellType::triangle, 2, 2); // Create vertices and cells: if (diagonal == "crossed") { editor.init_vertices_global((nx + 1)*(ny + 1) + nx*ny, (nx + 1)*(ny + 1) + nx*ny); editor.init_cells_global(4*nx*ny, 4*nx*ny); } else { editor.init_vertices_global((nx + 1)*(ny + 1), (nx + 1)*(ny + 1)); editor.init_cells_global(2*nx*ny, 2*nx*ny); } // Storage for vertices std::vector<double> x(2); // Create main vertices: std::size_t vertex = 0; for (std::size_t iy = 0; iy <= ny; iy++) { x[1] = c + ((static_cast<double>(iy))*(d - c)/static_cast<double>(ny)); for (std::size_t ix = 0; ix <= nx; ix++) { x[0] = a + ((static_cast<double>(ix))*(b - a)/static_cast<double>(nx)); editor.add_vertex(vertex, x); vertex++; } } // Create midpoint vertices if the mesh type is crossed if (diagonal == "crossed") { for (std::size_t iy = 0; iy < ny; iy++) { x[1] = c +(static_cast<double>(iy) + 0.5)*(d - c)/static_cast<double>(ny); for (std::size_t ix = 0; ix < nx; ix++) { x[0] = a + (static_cast<double>(ix) + 0.5)*(b - a)/static_cast<double>(nx); editor.add_vertex(vertex, x); vertex++; } } } // Create triangles std::size_t cell = 0; if (diagonal == "crossed") { boost::multi_array<std::size_t, 2> cells(boost::extents[4][3]); for (std::size_t iy = 0; iy < ny; iy++) { for (std::size_t ix = 0; ix < nx; ix++) { const std::size_t v0 = iy*(nx + 1) + ix; const std::size_t v1 = v0 + 1; const std::size_t v2 = v0 + (nx + 1); const std::size_t v3 = v1 + (nx + 1); const std::size_t vmid = (nx + 1)*(ny + 1) + iy*nx + ix; // Note that v0 < v1 < v2 < v3 < vmid. cells[0][0] = v0; cells[0][1] = v1; cells[0][2] = vmid; cells[1][0] = v0; cells[1][1] = v2; cells[1][2] = vmid; cells[2][0] = v1; cells[2][1] = v3; cells[2][2] = vmid; cells[3][0] = v2; cells[3][1] = v3; cells[3][2] = vmid; // Add cells for (auto _cell = cells.begin(); _cell != cells.end(); ++_cell) editor.add_cell(cell++, *_cell); } } } else if (diagonal == "left" || diagonal == "right" || diagonal == "right/left" || diagonal == "left/right") { std::string local_diagonal = diagonal; boost::multi_array<std::size_t, 2> cells(boost::extents[2][3]); for (std::size_t iy = 0; iy < ny; iy++) { // Set up alternating diagonal if (diagonal == "right/left") { if (iy % 2) local_diagonal = "right"; else local_diagonal = "left"; } if (diagonal == "left/right") { if (iy % 2) local_diagonal = "left"; else local_diagonal = "right"; } for (std::size_t ix = 0; ix < nx; ix++) { const std::size_t v0 = iy*(nx + 1) + ix; const std::size_t v1 = v0 + 1; const std::size_t v2 = v0 + (nx + 1); const std::size_t v3 = v1 + (nx + 1); std::vector<std::size_t> cell_data; if(local_diagonal == "left") { cells[0][0] = v0; cells[0][1] = v1; cells[0][2] = v2; cells[1][0] = v1; cells[1][1] = v2; cells[1][2] = v3; if (diagonal == "right/left" || diagonal == "left/right") local_diagonal = "right"; } else { cells[0][0] = v0; cells[0][1] = v1; cells[0][2] = v3; cells[1][0] = v0; cells[1][1] = v2; cells[1][2] = v3; if (diagonal == "right/left" || diagonal == "left/right") local_diagonal = "left"; } editor.add_cell(cell++, cells[0]); editor.add_cell(cell++, cells[1]); } } } // Close mesh editor editor.close(); // Broadcast mesh according to parallel policy if (MPI::is_broadcaster(this->mpi_comm())) { MeshPartitioning::build_distributed_mesh(*this); return; } }
void animate() { //usleep( (int)1e4 ); me.try_spinning_ball(); glutPostRedisplay(); }
//----------------------------------------------------------------------------- void UniformMeshRefinement::refine(Mesh& refined_mesh, const Mesh& mesh) { not_working_in_parallel("UniformMeshRefinement::refine"); log(TRACE, "Refining simplicial mesh uniformly."); // Check that refined_mesh and mesh are not the same if (&refined_mesh == &mesh) { dolfin_error("UniformMeshRefinement.cpp", "refine mesh", "Refined_mesh and mesh point to the same object"); } // Generate cell - edge connectivity if not generated mesh.init(mesh.topology().dim(), 1); // Generate edge - vertex connectivity if not generated mesh.init(1, 0); // Mesh needs to be ordered (so we can pick right combination of vertices/edges) if (!mesh.ordered()) dolfin_error("UniformMeshRefinement.cpp", "refine mesh", "Mesh is not ordered according to the UFC numbering convention, consider calling mesh.order()"); // Get cell type const CellType& cell_type = mesh.type(); // Open new mesh for editing MeshEditor editor; editor.open(refined_mesh, cell_type.cell_type(), mesh.topology().dim(), mesh.geometry().dim()); // Get size of mesh const std::size_t num_vertices = mesh.size(0); const std::size_t num_edges = mesh.size(1); const std::size_t num_cells = mesh.size(mesh.topology().dim()); // Specify number of vertices and cells editor.init_vertices_global(num_vertices + num_edges, num_vertices + num_edges); editor.init_cells_global(ipow(2, mesh.topology().dim())*num_cells, ipow(2, mesh.topology().dim())*num_cells); // Add old vertices std::size_t vertex = 0; for (VertexIterator v(mesh); !v.end(); ++v) { editor.add_vertex(vertex, v->point()); vertex++; } // Add new vertices for (EdgeIterator e(mesh); !e.end(); ++e) { editor.add_vertex(vertex, e->midpoint()); vertex++; } // Add cells std::size_t current_cell = 0; for (CellIterator c(mesh); !c.end(); ++c) cell_type.refine_cell(*c, editor, current_cell); // Close editor editor.close(); // Make sure that mesh is ordered after refinement //refined_mesh.order(); }
//----------------------------------------------------------------------------- void IntervalMesh::build(std::size_t nx, double a, double b) { // Receive mesh according to parallel policy if (MPI::is_receiver(this->mpi_comm())) { MeshPartitioning::build_distributed_mesh(*this); return; } if (std::abs(a - b) < DOLFIN_EPS) { dolfin_error("Interval.cpp", "create interval", "Length of interval is zero. Consider checking your dimensions"); } if (b < a) { dolfin_error("Interval.cpp", "create interval", "Length of interval is negative. Consider checking the order of your arguments"); } if (nx < 1) { dolfin_error("Interval.cpp", "create interval", "Number of points on interval is (%d), it must be at least 1", nx); } rename("mesh", "Mesh of the interval (a, b)"); // Open mesh for editing MeshEditor editor; editor.open(*this, CellType::interval, 1, 1); // Create vertices and cells: editor.init_vertices_global((nx+1), (nx+1)); editor.init_cells_global(nx, nx); // Create main vertices: for (std::size_t ix = 0; ix <= nx; ix++) { const std::vector<double> x(1, a + (static_cast<double>(ix)*(b - a)/static_cast<double>(nx))); editor.add_vertex(ix, x); } // Create intervals for (std::size_t ix = 0; ix < nx; ix++) { std::vector<std::size_t> cell(2); cell[0] = ix; cell[1] = ix + 1; editor.add_cell(ix, cell); } // Close mesh editor editor.close(); // Broadcast mesh according to parallel policy if (MPI::is_broadcaster(this->mpi_comm())) { std::cout << "Building mesh (dist 0a)" << std::endl; MeshPartitioning::build_distributed_mesh(*this); std::cout << "Building mesh (dist 1a)" << std::endl; return; } }
//----------------------------------------------------------------------------- dolfin::Mesh MeshRenumbering::renumber_by_color(const Mesh& mesh, const std::vector<std::size_t> coloring_type) { // Start timer Timer timer("Renumber mesh by color"); // Get some some mesh const std::size_t tdim = mesh.topology().dim(); const std::size_t gdim = mesh.geometry().dim(); const std::size_t num_vertices = mesh.num_vertices(); const std::size_t num_cells = mesh.num_cells(); // Check that requested coloring is a cell coloring if (coloring_type[0] != tdim) { dolfin_error("MeshRenumbering.cpp", "renumber mesh by color", "Coloring is not a cell coloring: only cell colorings are supported"); } // Compute renumbering std::vector<double> new_coordinates; std::vector<std::size_t> new_connections; MeshRenumbering::compute_renumbering(mesh, coloring_type, new_coordinates, new_connections); // Create new mesh Mesh new_mesh; // Create mesh editor MeshEditor editor; editor.open(new_mesh, mesh.type().cell_type(), tdim, gdim); editor.init_cells(num_cells); editor.init_vertices(num_vertices); // Add vertices dolfin_assert(new_coordinates.size() == num_vertices*gdim); for (std::size_t i = 0; i < num_vertices; ++i) { std::vector<double> x(gdim); for (std::size_t j = 0; j < gdim; ++j) x[j] = new_coordinates[i*gdim + j]; editor.add_vertex(i, x); } cout << "Done adding vertices" << endl; // Add cells dolfin_assert(new_coordinates.size() == num_vertices*gdim); const std::size_t vertices_per_cell = mesh.type().num_entities(0); for (std::size_t i = 0; i < num_cells; ++i) { std::vector<std::size_t> c(vertices_per_cell); std::copy(new_connections.begin() + i*vertices_per_cell, new_connections.begin() + i*vertices_per_cell + vertices_per_cell, c.begin()); editor.add_cell(i, c); } editor.close(); cout << "Close editor" << endl; // Initialise coloring data typedef std::map<const std::vector<std::size_t>, std::pair<std::vector<std::size_t>, std::vector<std::vector<std::size_t> > > >::const_iterator ConstMeshColoringData; // Get old coloring ConstMeshColoringData mesh_coloring = mesh.topology().coloring.find(coloring_type); if (mesh_coloring == mesh.topology().coloring.end()) { dolfin_error("MeshRenumbering.cpp", "renumber mesh by color", "Requested mesh coloring has not been computed"); } // Get old coloring data const std::vector<std::size_t>& colors = mesh_coloring->second.first; const std::vector<std::vector<std::size_t> >& entities_of_color = mesh_coloring->second.second; dolfin_assert(colors.size() == num_cells); dolfin_assert(!entities_of_color.empty()); const std::size_t num_colors = entities_of_color.size(); // New coloring data dolfin_assert(new_mesh.topology().coloring.empty()); std::vector<std::size_t> new_colors(colors.size()); std::vector<std::vector<std::size_t> > new_entities_of_color(num_colors); std::size_t current_cell = 0; for (std::size_t color = 0; color < num_colors; color++) { // Get the array of cell indices of current color const std::vector<std::size_t>& colored_cells = entities_of_color[color]; std::vector<std::size_t>& new_colored_cells = new_entities_of_color[color]; // Update cell color data for (std::size_t i = 0; i < colored_cells.size(); i++) { new_colored_cells.push_back(current_cell); new_colors[current_cell] = color; current_cell++; } } // Set new coloring mesh data std::pair<ConstMeshColoringData, bool> insert = new_mesh.topology().coloring.insert(std::make_pair(coloring_type, std::make_pair(new_colors, new_entities_of_color))); dolfin_assert(insert.second); cout << "Return new mesh" << endl; return new_mesh; }
//----------------------------------------------------------------------------- void RegularCutRefinement::refine_marked(Mesh& refined_mesh, const Mesh& mesh, const std::vector<int>& refinement_markers, const IndexSet& marked_edges) { // Count the number of cells in refined mesh std::size_t num_cells = 0; // Data structure to hold a cell std::vector<std::size_t> cell_data(3); for (CellIterator cell(mesh); !cell.end(); ++cell) { const int marker = refinement_markers[cell->index()]; switch (marker) { case no_refinement: num_cells += 1; break; case regular_refinement: num_cells += 4; break; case backtrack_bisection: num_cells += 2; break; case backtrack_bisection_refine: num_cells += 3; break; default: num_cells += 2; } } // Initialize mesh editor const std::size_t num_vertices = mesh.num_vertices() + marked_edges.size(); MeshEditor editor; editor.open(refined_mesh, mesh.topology().dim(), mesh.geometry().dim()); editor.init_vertices(num_vertices); editor.init_cells(num_cells); // Set vertex coordinates std::size_t current_vertex = 0; for (VertexIterator vertex(mesh); !vertex.end(); ++vertex) { editor.add_vertex(current_vertex, vertex->point()); current_vertex++; } for (std::size_t i = 0; i < marked_edges.size(); i++) { Edge edge(mesh, marked_edges[i]); editor.add_vertex(current_vertex, edge.midpoint()); current_vertex++; } // Get bisection data for old mesh const std::size_t D = mesh.topology().dim(); const std::vector<std::size_t>* bisection_twins = NULL; if (mesh.data().exists("bisection_twins", D)) bisection_twins = &(mesh.data().array("bisection_twins", D)); // Markers for bisected cells pointing to their bisection twins in // refined mesh std::vector<std::size_t>& refined_bisection_twins = refined_mesh.data().create_array("bisection_twins", D); refined_bisection_twins.resize(num_cells); for (std::size_t i = 0; i < num_cells; i++) refined_bisection_twins[i] = i; // Mapping from old to new unrefined cells (-1 means refined or not // yet processed) std::vector<int> unrefined_cells(mesh.num_cells()); std::fill(unrefined_cells.begin(), unrefined_cells.end(), -1); // Iterate over all cells and add new cells std::size_t current_cell = 0; std::vector<std::vector<std::size_t> > cells(4, std::vector<std::size_t>(3)); for (CellIterator cell(mesh); !cell.end(); ++cell) { // Get marker const int marker = refinement_markers[cell->index()]; if (marker == no_refinement) { // No refinement: just copy cell to new mesh std::vector<std::size_t> vertices; for (VertexIterator vertex(*cell); !vertex.end(); ++vertex) vertices.push_back(vertex->index()); editor.add_cell(current_cell++, vertices); // Store mapping to new cell index unrefined_cells[cell->index()] = current_cell - 1; // Remember unrefined bisection twins if (bisection_twins) { const std::size_t bisection_twin = (*bisection_twins)[cell->index()]; const int twin_marker = refinement_markers[bisection_twin]; dolfin_assert(twin_marker == no_refinement); if (unrefined_cells[bisection_twin] >= 0) { const std::size_t i = current_cell - 1; const std::size_t j = unrefined_cells[bisection_twin]; refined_bisection_twins[i] = j; refined_bisection_twins[j] = i; } } } else if (marker == regular_refinement) { // Regular refinement: divide into subsimplicies dolfin_assert(unrefined_cells[cell->index()] == -1); // Get vertices and edges const unsigned int* v = cell->entities(0); const unsigned int* e = cell->entities(1); dolfin_assert(v); dolfin_assert(e); // Get offset for new vertex indices const std::size_t offset = mesh.num_vertices(); // Compute indices for the six new vertices const std::size_t v0 = v[0]; const std::size_t v1 = v[1]; const std::size_t v2 = v[2]; const std::size_t e0 = offset + marked_edges.find(e[0]); const std::size_t e1 = offset + marked_edges.find(e[1]); const std::size_t e2 = offset + marked_edges.find(e[2]); // Create four new cells cells[0][0] = v0; cells[0][1] = e2; cells[0][2] = e1; cells[1][0] = v1; cells[1][1] = e0; cells[1][2] = e2; cells[2][0] = v2; cells[2][1] = e1; cells[2][2] = e0; cells[3][0] = e0; cells[3][1] = e1; cells[3][2] = e2; // Add cells std::vector<std::vector<std::size_t> >::const_iterator _cell; for (_cell = cells.begin(); _cell != cells.end(); ++_cell) editor.add_cell(current_cell++, *_cell); } else if (marker == backtrack_bisection || marker == backtrack_bisection_refine) { // Special case: backtrack bisected cells dolfin_assert(unrefined_cells[cell->index()] == -1); // Get index for bisection twin dolfin_assert(bisection_twins); const std::size_t bisection_twin = (*bisection_twins)[cell->index()]; dolfin_assert(bisection_twin != cell->index()); // Let lowest number twin handle refinement if (bisection_twin < cell->index()) continue; // Get marker for twin const int twin_marker = refinement_markers[bisection_twin]; // Find common edge(s) and bisected edge(s) const std::pair<std::size_t, std::size_t> common_edges = find_common_edges(*cell, mesh, bisection_twin); const std::pair<std::size_t, std::size_t> bisection_edges = find_bisection_edges(*cell, mesh, bisection_twin); const std::pair<std::size_t, std::size_t> bisection_vertices = find_bisection_vertices(*cell, mesh, bisection_twin, bisection_edges); // Get list of vertices and edges for both cells const Cell twin(mesh, bisection_twin); const unsigned int* vertices_0 = cell->entities(0); const unsigned int* vertices_1 = twin.entities(0); const unsigned int* edges_0 = cell->entities(1); const unsigned int* edges_1 = twin.entities(1); dolfin_assert(vertices_0); dolfin_assert(vertices_1); dolfin_assert(edges_0); dolfin_assert(edges_1); // Get offset for new vertex indices const std::size_t offset = mesh.num_vertices(); // Locate vertices such that v_i is the vertex opposite to // the edge e_i on the parent triangle const std::size_t v0 = vertices_0[common_edges.first]; const std::size_t v1 = vertices_1[common_edges.second]; const std::size_t v2 = vertices_0[bisection_edges.first]; const std::size_t e0 = offset + marked_edges.find(edges_1[bisection_vertices.second]); const std::size_t e1 = offset + marked_edges.find(edges_0[bisection_vertices.first]); const std::size_t e2 = vertices_0[bisection_vertices.first]; // Locate new vertices on bisected edge (if any) std::size_t E0 = 0; std::size_t E1 = 0; if (marker == backtrack_bisection_refine) E0 = offset + marked_edges.find(edges_0[bisection_edges.first]); if (twin_marker == backtrack_bisection_refine) E1 = offset + marked_edges.find(edges_1[bisection_edges.second]); // Add middle two cells (always) dolfin_assert(cell_data.size() == 3); cell_data[0] = e0; cell_data[1] = e1; cell_data[2] = e2; editor.add_cell(current_cell++, cell_data); cell_data[0] = v2; cell_data[1] = e1; cell_data[2] = e0; editor.add_cell(current_cell++, cell_data); // Add one or two remaining cells in current cell (left) if (marker == backtrack_bisection) { cell_data[0] = v0; cell_data[1] = e2; cell_data[2] = e1; editor.add_cell(current_cell++, cell_data); } else { // Add the two cells cell_data[0] = v0; cell_data[1] = E0; cell_data[2] = e1; editor.add_cell(current_cell++, cell_data); cell_data[0] = E0; cell_data[1] = e2; cell_data[2] = e1; editor.add_cell(current_cell++, cell_data); // Set bisection twins refined_bisection_twins[current_cell - 2] = current_cell - 1; refined_bisection_twins[current_cell - 1] = current_cell - 2; } // Add one or two remaining cells in twin cell (right) if (twin_marker == backtrack_bisection) { cell_data[0] = v1; cell_data[1] = e0; cell_data[2] = e2; editor.add_cell(current_cell++, cell_data); } else { // Add the two cells cell_data[0] = v1; cell_data[1] = e0; cell_data[2] = E1; editor.add_cell(current_cell++, cell_data); cell_data[0] = e0; cell_data[1] = e2; cell_data[2] = E1; editor.add_cell(current_cell++, cell_data); // Set bisection twins refined_bisection_twins[current_cell - 2] = current_cell - 1; refined_bisection_twins[current_cell - 1] = current_cell - 2; } } else { // One edge marked for refinement: do bisection dolfin_assert(unrefined_cells[cell->index()] == -1); // Get vertices and edges const unsigned int* v = cell->entities(0); const unsigned int* e = cell->entities(1); dolfin_assert(v); dolfin_assert(e); // Get edge number (equal to marker) dolfin_assert(marker >= 0); const std::size_t local_edge_index = static_cast<std::size_t>(marker); const std::size_t global_edge_index = e[local_edge_index]; const std::size_t ee = mesh.num_vertices() + marked_edges.find(global_edge_index); // Add the two new cells if (local_edge_index == 0) { cell_data[0] = v[0]; cell_data[1] = ee; cell_data[2] = v[1]; editor.add_cell(current_cell++, cell_data); cell_data[0] = v[0]; cell_data[1] = ee; cell_data[2] = v[2]; editor.add_cell(current_cell++, cell_data); } else if (local_edge_index == 1) { cell_data[0] = v[1]; cell_data[1] = ee; cell_data[2] = v[0]; editor.add_cell(current_cell++, cell_data); cell_data[0] = v[1]; cell_data[1] = ee; cell_data[2] = v[2]; editor.add_cell(current_cell++, cell_data); } else { cell_data[0] = v[2]; cell_data[1] = ee; cell_data[2] = v[0]; editor.add_cell(current_cell++, cell_data); cell_data[0] = v[2]; cell_data[1] = ee; cell_data[2] = v[1]; editor.add_cell(current_cell++, cell_data); } // Set bisection twins refined_bisection_twins[current_cell - 2] = current_cell - 1; refined_bisection_twins[current_cell - 1] = current_cell - 2; } } // Close mesh editor dolfin_assert(num_cells == current_cell); editor.close(); }
//----------------------------------------------------------------------------- UnitHexMesh::UnitHexMesh(MPI_Comm comm, std::size_t nx, std::size_t ny, std::size_t nz) : Mesh(comm) { // Receive mesh according to parallel policy if (MPI::is_receiver(this->mpi_comm())) { MeshPartitioning::build_distributed_mesh(*this); return; } MeshEditor editor; editor.open(*this, CellType::hexahedron, 3, 3); // Create vertices and cells: editor.init_vertices_global((nx + 1)*(ny + 1)*(nz + 1), (nx + 1)*(ny + 1)*(nz + 1)); editor.init_cells_global(nx*ny*nz, nx*ny*nz); // Storage for vertices std::vector<double> x(3); const double a = 0.0; const double b = 1.0; const double c = 0.0; const double d = 1.0; const double e = 0.0; const double f = 1.0; // Create main vertices: std::size_t vertex = 0; for (std::size_t iz = 0; iz <= nz; iz++) { x[2] = e + ((static_cast<double>(iz))*(f - e)/static_cast<double>(nz)); for (std::size_t iy = 0; iy <= ny; iy++) { x[1] = c + ((static_cast<double>(iy))*(d - c)/static_cast<double>(ny)); for (std::size_t ix = 0; ix <= nx; ix++) { x[0] = a + ((static_cast<double>(ix))*(b - a)/static_cast<double>(nx)); editor.add_vertex(vertex, x); vertex++; } } } // Create cuboids std::size_t cell = 0; std::vector<std::size_t> v(8); for (std::size_t iz = 0; iz < nz; iz++) for (std::size_t iy = 0; iy < ny; iy++) for (std::size_t ix = 0; ix < nx; ix++) { v[0] = (iz*(ny + 1) + iy)*(nx + 1) + ix; v[1] = v[0] + 1; v[2] = v[0] + (nx + 1); v[3] = v[1] + (nx + 1); v[4] = v[0] + (nx + 1)*(ny + 1); v[5] = v[1] + (nx + 1)*(ny + 1); v[6] = v[2] + (nx + 1)*(ny + 1); v[7] = v[3] + (nx + 1)*(ny + 1); editor.add_cell(cell, v); ++cell; } // Close mesh editor editor.close(); // Broadcast mesh according to parallel policy if (MPI::is_broadcaster(this->mpi_comm())) { MeshPartitioning::build_distributed_mesh(*this); return; } }
//----------------------------------------------------------------------------- void MeshPartitioning::build_mesh(Mesh& mesh, const std::vector<std::size_t>& global_cell_indices, const boost::multi_array<std::size_t, 2>& cell_global_vertices, const std::vector<std::size_t>& vertex_indices, const boost::multi_array<double, 2>& vertex_coordinates, const std::map<std::size_t, std::size_t>& vertex_global_to_local, std::size_t tdim, std::size_t gdim, std::size_t num_global_cells, std::size_t num_global_vertices) { Timer timer("PARALLEL 3: Build mesh (from local mesh data)"); // Get number of processes and process number const std::size_t num_processes = MPI::num_processes(); const std::size_t process_number = MPI::process_number(); // Open mesh for editing mesh.clear(); MeshEditor editor; editor.open(mesh, tdim, gdim); // Add vertices editor.init_vertices(vertex_coordinates.size()); Point point(gdim); dolfin_assert(vertex_indices.size() == vertex_coordinates.size()); for (std::size_t i = 0; i < vertex_coordinates.size(); ++i) { for (std::size_t j = 0; j < gdim; ++j) point[j] = vertex_coordinates[i][j]; editor.add_vertex_global(i, vertex_indices[i], point); } // Add cells editor.init_cells(cell_global_vertices.size()); const std::size_t num_cell_vertices = tdim + 1; std::vector<std::size_t> cell(num_cell_vertices); for (std::size_t i = 0; i < cell_global_vertices.size(); ++i) { for (std::size_t j = 0; j < num_cell_vertices; ++j) { // Get local cell vertex std::map<std::size_t, std::size_t>::const_iterator iter = vertex_global_to_local.find(cell_global_vertices[i][j]); dolfin_assert(iter != vertex_global_to_local.end()); cell[j] = iter->second; } editor.add_cell(i, global_cell_indices[i], cell); } // Close mesh: Note that this must be done after creating the global // vertex map or otherwise the ordering in mesh.close() will be wrong // (based on local numbers). editor.close(); // Set global number of cells and vertices mesh.topology().init_global(0, num_global_vertices); mesh.topology().init_global(tdim, num_global_cells); // Construct boundary mesh BoundaryMesh bmesh(mesh, "exterior"); const MeshFunction<std::size_t>& boundary_vertex_map = bmesh.entity_map(0); const std::size_t boundary_size = boundary_vertex_map.size(); // Build sorted array of global boundary vertex indices (global // numbering) std::vector<std::size_t> global_vertex_send(boundary_size); for (std::size_t i = 0; i < boundary_size; ++i) global_vertex_send[i] = vertex_indices[boundary_vertex_map[i]]; std::sort(global_vertex_send.begin(), global_vertex_send.end()); // Receive buffer std::vector<std::size_t> global_vertex_recv; // Create shared_vertices data structure: mapping from shared vertices // to list of neighboring processes std::map<unsigned int, std::set<unsigned int> >& shared_vertices = mesh.topology().shared_entities(0); shared_vertices.clear(); // FIXME: Remove computation from inside communication loop // Build shared vertex to sharing processes map for (std::size_t i = 1; i < num_processes; ++i) { // We send data to process p - i (i steps to the left) const int p = (process_number - i + num_processes) % num_processes; // We receive data from process p + i (i steps to the right) const int q = (process_number + i) % num_processes; // Send and receive MPI::send_recv(global_vertex_send, p, global_vertex_recv, q); // Compute intersection of global indices std::vector<std::size_t> intersection(std::min(global_vertex_send.size(), global_vertex_recv.size())); std::vector<std::size_t>::iterator intersection_end = std::set_intersection(global_vertex_send.begin(), global_vertex_send.end(), global_vertex_recv.begin(), global_vertex_recv.end(), intersection.begin()); // Fill shared vertices information std::vector<std::size_t>::const_iterator global_index; for (global_index = intersection.begin(); global_index != intersection_end; ++global_index) { // Get local index std::map<std::size_t, std::size_t>::const_iterator local_index; local_index = vertex_global_to_local.find(*global_index); dolfin_assert(local_index != vertex_global_to_local.end()); // Insert (local index, [proc]) shared_vertices[local_index->second].insert(q); } } }
//----------------------------------------------------------------------------- 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; } } } } }
void reshape(int W, int H) { me.reshape(W,H); }
//----------------------------------------------------------------------------- UnitDiscMesh::UnitDiscMesh(MPI_Comm comm, std::size_t n, std::size_t degree, std::size_t gdim) : Mesh(comm) { dolfin_assert(n > 0); dolfin_assert(gdim == 2 or gdim == 3); dolfin_assert(degree == 1 or degree == 2); MeshEditor editor; editor.open(*this, 2, gdim, degree); editor.init_vertices_global(1 + 3*n*(n + 1), 1 + 3*n*(n + 1)); std::size_t c = 0; editor.add_vertex(c, Point(0,0,0)); ++c; for (std::size_t i = 1; i <= n; ++i) for (std::size_t j = 0; j < 6*i; ++j) { double r = (double)i/(double)n; double th = 2*M_PI*(double)j/(double)(6*i); double x = r*cos(th); double y = r*sin(th); editor.add_vertex(c, Point(x, y, 0)); ++c; } editor.init_cells(6*n*n); c = 0; std::size_t base_i = 0; std::size_t row_i = 1; for (std::size_t i = 1; i <= n; ++i) { std::size_t base_m = base_i; base_i = 1 + 3*i*(i - 1); std::size_t row_m = row_i; row_i = 6*i; for (std::size_t k = 0; k != 6; ++k) for (std::size_t j = 0; j < (i*2 - 1); ++j) { std::size_t i0, i1, i2; if (j%2 == 0) { i0 = base_i + (k*i + j/2)%row_i; i1 = base_i + (k*i + j/2 + 1)%row_i; i2 = base_m + (k*(i-1) + j/2)%row_m; } else { i0 = base_m + (k*(i-1) + j/2)%row_m; i1 = base_m + (k*(i-1) + j/2 + 1)%row_m; i2 = base_i + (k*i + j/2 + 1)%row_i; } editor.add_cell(c, i0, i1, i2); ++c; } } // Initialise entities required for this degree polynomial mesh // and allocate space for the point coordinate data if (degree == 2) { editor.init_entities(); for (EdgeIterator e(*this); !e.end(); ++e) { Point v0 = Vertex(*this, e->entities(0)[0]).point(); Point v1 = Vertex(*this, e->entities(0)[1]).point(); Point pt = e->midpoint(); if (std::abs(v0.norm() - 1.0) < 1e-6 and std::abs(v1.norm() - 1.0) < 1e-6) pt *= v0.norm()/pt.norm(); // Add Edge-based point editor.add_entity_point(1, 0, e->index(), pt); } } editor.close(); }
int main(int argc, char *argv[]) { if (argc < 3 ) { std::cout<< "Usage: ./extract <checkpoint> <num>" << std::endl; return 0; } std::ostringstream _fname; _fname << argv[1] << "_"; std::vector<std::string> chkp_files; for (int i = 0; i < atoi(argv[2]); i++) { std::ostringstream tmp; tmp << _fname.str(); tmp << i << ".chkp"; chkp_files.push_back(tmp.str()); } CellType::Type type; double t; unsigned int id, tdim, gdim, num_vertices, num_cells, num_entities; std::ifstream in; std::list<dVertex> vlist; std::list<dCell> dmesh; for(std::vector<std::string>::iterator it = chkp_files.begin(); it != chkp_files.end(); ++it) { in.open(it->c_str(), std::ifstream::binary); if(in.good()) { in.read((char *)&id, sizeof(unsigned int)); in.read((char *)&t, sizeof(double)); in.read((char *)&type, sizeof(CellType::Type)); in.read((char *)&tdim, sizeof(unsigned int)); in.read((char *)&gdim, sizeof(unsigned int)); in.read((char *)&num_vertices, sizeof(unsigned int)); in.read((char *)&num_cells, sizeof(unsigned int)); in.read((char *)&num_entities, sizeof(unsigned int)); double *coords = new double[gdim *num_vertices]; in.read((char *)coords, (gdim * num_vertices) * sizeof(double)); std::list<dVertex> _vlist; int vi = 0; for(unsigned int i = 0; i < gdim * num_vertices; i += gdim) { switch(gdim) { case 2: _vlist.push_back(dVertex(vi++, Point(coords[i], coords[i+1]))); break; case 3: _vlist.push_back(dVertex(vi++, Point(coords[i], coords[i+1], coords[i+2]))); break; } } delete[] coords; unsigned int *cells = new unsigned int[num_entities * num_cells]; in.read((char *)cells, (num_entities * num_cells) * sizeof(unsigned int)); unsigned int *mapping = new unsigned int[_vlist.size()]; in.read((char *)mapping, _vlist.size() * sizeof(unsigned int)); unsigned int *mp = &mapping[0]; std::map<unsigned int, unsigned int> vmap; for(std::list<dVertex>::iterator it = _vlist.begin(); it != _vlist.end(); ++it) vmap[it->id] = *(mp++); delete[] mapping; Array<unsigned int> v; for(unsigned int i = 0; i < num_entities * num_cells; i += num_entities) { v.clear(); for(unsigned int j = 0; j < num_entities; j++) v.push_back(vmap[cells[i+j]]); dmesh.push_back(dCell(v)); } delete[] cells; unsigned int num_ghost; in.read((char *)&num_ghost, sizeof(unsigned int)); unsigned int *ghosts = new unsigned int[2 * num_ghost]; in.read((char *)ghosts, 2*num_ghost * sizeof(unsigned int)); std::set<unsigned int> ghost_set; for (unsigned int i = 0; i < 2 * num_ghost; i += 2) ghost_set.insert(ghosts[i]); delete[] ghosts; for(std::list<dVertex>::iterator it = _vlist.begin(); it != _vlist.end(); ++it) if(ghost_set.find(it->id) == ghost_set.end()) vlist.push_back(dVertex(vmap[it->id], it->p)); } in.close(); } Mesh mesh; MeshEditor editor; editor.open(mesh, type, tdim, gdim); editor.initVertices(vlist.size()); editor.initCells(dmesh.size()); for(std::list<dVertex>::iterator it = vlist.begin(); it != vlist.end(); ++it) editor.addVertex(it->id, it->p); unsigned int ci = 0; for(std::list<dCell>::iterator it = dmesh.begin(); it != dmesh.end(); ++it) editor.addCell(ci++, it->vertices); editor.close(); File mesh_file("mesh.xml"); mesh_file << mesh; }
//----------------------------------------------------------------------------- void XMLMesh::read_mesh(Mesh& mesh, const pugi::xml_node mesh_node) { // Get cell type and geometric dimension const std::string cell_type_str = mesh_node.attribute("celltype").value(); const std::size_t gdim = mesh_node.attribute("dim").as_uint(); // Get topological dimension boost::scoped_ptr<CellType> cell_type(CellType::create(cell_type_str)); const std::size_t tdim = cell_type->dim(); // Create mesh for editing MeshEditor editor; editor.open(mesh, cell_type_str, tdim, gdim); // Get vertices xml node pugi::xml_node xml_vertices = mesh_node.child("vertices"); dolfin_assert(xml_vertices); // Get number of vertices and init editor const std::size_t num_vertices = xml_vertices.attribute("size").as_uint(); editor.init_vertices_global(num_vertices, num_vertices); // Iterate over vertices and add to mesh Point p; for (pugi::xml_node_iterator it = xml_vertices.begin(); it != xml_vertices.end(); ++it) { const std::size_t index = it->attribute("index").as_uint(); p[0] = it->attribute("x").as_double(); p[1] = it->attribute("y").as_double(); p[2] = it->attribute("z").as_double(); editor.add_vertex(index, p); } // Get cells node pugi::xml_node xml_cells = mesh_node.child("cells"); dolfin_assert(xml_cells); // Get number of cells and init editor const std::size_t num_cells = xml_cells.attribute("size").as_uint(); editor.init_cells_global(num_cells, num_cells); // Create list of vertex index attribute names const unsigned int num_vertices_per_cell = cell_type->num_vertices(tdim); std::vector<std::string> v_str(num_vertices_per_cell); for (std::size_t i = 0; i < num_vertices_per_cell; ++i) v_str[i] = "v" + boost::lexical_cast<std::string, unsigned int>(i); // Iterate over cells and add to mesh std::vector<std::size_t> v(num_vertices_per_cell); for (pugi::xml_node_iterator it = xml_cells.begin(); it != xml_cells.end(); ++it) { const std::size_t index = it->attribute("index").as_uint(); for (unsigned int i = 0; i < num_vertices_per_cell; ++i) v[i] = it->attribute(v_str[i].c_str()).as_uint(); editor.add_cell(index, v); } // Close mesh editor editor.close(); }
void motion(int x, int y) { Vec2i pos(x,WINY-y); me.roll_ball(pos); }