UniquePtr<Elem> Tri::side (const unsigned int i) const { libmesh_assert_less (i, this->n_sides()); Elem* edge = new Edge2; switch (i) { case 0: { edge->set_node(0) = this->get_node(0); edge->set_node(1) = this->get_node(1); break; } case 1: { edge->set_node(0) = this->get_node(1); edge->set_node(1) = this->get_node(2); break; } case 2: { edge->set_node(0) = this->get_node(2); edge->set_node(1) = this->get_node(0); break; } default: libmesh_error_msg("Invalid side i = " << i); } return UniquePtr<Elem>(edge); }
AutoPtr<Elem> Quad::side (const unsigned int i) const { libmesh_assert_less (i, this->n_sides()); Elem* edge = new Edge2; switch (i) { case 0: { edge->set_node(0) = this->get_node(0); edge->set_node(1) = this->get_node(1); AutoPtr<Elem> ap_edge(edge); return ap_edge; } case 1: { edge->set_node(0) = this->get_node(1); edge->set_node(1) = this->get_node(2); AutoPtr<Elem> ap_edge(edge); return ap_edge; } case 2: { edge->set_node(0) = this->get_node(2); edge->set_node(1) = this->get_node(3); AutoPtr<Elem> ap_edge(edge); return ap_edge; } case 3: { edge->set_node(0) = this->get_node(3); edge->set_node(1) = this->get_node(0); AutoPtr<Elem> ap_edge(edge); return ap_edge; } default: { libmesh_error(); } } // We will never get here... Look at the code above. libmesh_error(); AutoPtr<Elem> ap_edge(edge); return ap_edge; }
UniquePtr<Elem> InfQuad::side (const unsigned int i) const { libmesh_assert_less (i, this->n_sides()); // To be returned wrapped in an UniquePtr Elem* edge = NULL; switch (i) { case 0: // base face { edge = new Edge2; break; } case 1: // adjacent to another infinite element case 2: // adjacent to another infinite element { edge = new InfEdge2; break; } default: libmesh_error_msg("Invalid side i = " << i); } // Set the nodes for (unsigned n=0; n<edge->n_nodes(); ++n) edge->set_node(n) = this->get_node(InfQuad4::side_nodes_map[i][n]); return UniquePtr<Elem>(edge); }
UniquePtr<Elem> Pyramid::side_ptr (const unsigned int i) { libmesh_assert_less (i, this->n_sides()); // To be returned wrapped in a UniquePtr Elem * face = libmesh_nullptr; // Set up the type of element switch (i) { case 0: // triangular face 1 case 1: // triangular face 2 case 2: // triangular face 3 case 3: // triangular face 4 { face = new Tri3; break; } case 4: // the quad face at z=0 { face = new Quad4; break; } default: libmesh_error_msg("Invalid side i = " << i); } // Set the nodes for (unsigned n=0; n<face->n_nodes(); ++n) face->set_node(n) = this->node_ptr(Pyramid5::side_nodes_map[i][n]); return UniquePtr<Elem>(face); }
UniquePtr<Elem> Prism::side (const unsigned int i) const { libmesh_assert_less (i, this->n_sides()); Elem * face = libmesh_nullptr; // Set up the type of element switch (i) { case 0: // the triangular face at z=0 case 4: // the triangular face at z=1 { face = new Tri3; break; } case 1: // the quad face at y=0 case 2: // the other quad face case 3: // the quad face at x=0 { face = new Quad4; break; } default: libmesh_error_msg("Invalid side i = " << i); } // Set the nodes for (unsigned n=0; n<face->n_nodes(); ++n) face->set_node(n) = this->node_ptr(Prism6::side_nodes_map[i][n]); return UniquePtr<Elem>(face); }
UniquePtr<Elem> Pyramid5::build_side_ptr (const unsigned int i, bool proxy) { libmesh_assert_less (i, this->n_sides()); if (proxy) { switch (i) { case 0: case 1: case 2: case 3: return UniquePtr<Elem>(new Side<Tri3,Pyramid5>(this,i)); case 4: return UniquePtr<Elem>(new Side<Quad4,Pyramid5>(this,i)); default: libmesh_error_msg("Invalid side i = " << i); } } else { // Create NULL pointer to be initialized, returned later. Elem * face = libmesh_nullptr; switch (i) { case 0: // triangular face 1 case 1: // triangular face 2 case 2: // triangular face 3 case 3: // triangular face 4 { face = new Tri3; break; } case 4: // the quad face at z=0 { face = new Quad4; break; } default: libmesh_error_msg("Invalid side i = " << i); } face->subdomain_id() = this->subdomain_id(); // Set the nodes for (unsigned n=0; n<face->n_nodes(); ++n) face->set_node(n) = this->node_ptr(Pyramid5::side_nodes_map[i][n]); return UniquePtr<Elem>(face); } libmesh_error_msg("We'll never get here!"); return UniquePtr<Elem>(); }
UniquePtr<Elem> Edge::build_side (const unsigned int i, bool) const { libmesh_assert_less (i, 2); const Elem* the_parent = this; Elem *nodeelem = new NodeElem(const_cast<Elem*>(the_parent)); nodeelem->set_node(0) = this->get_node(i); return UniquePtr<Elem>(nodeelem); }
void build_mesh() { _mesh = new SerialMesh(*TestCommWorld); /* (0,1) (1,1) x---------------x | | | | | | | | | | x---------------x (0,0) (1,0) | | | | | | | | x---------------x (0,-1) (1,-1) */ _mesh->set_mesh_dimension(2); _mesh->add_point( Point(0.0,-1.0), 4 ); _mesh->add_point( Point(1.0,-1.0), 5 ); _mesh->add_point( Point(1.0, 0.0), 1 ); _mesh->add_point( Point(1.0, 1.0), 2 ); _mesh->add_point( Point(0.0, 1.0), 3 ); _mesh->add_point( Point(0.0, 0.0), 0 ); { Elem* elem_top = _mesh->add_elem( new Quad4 ); elem_top->set_node(0) = _mesh->node_ptr(0); elem_top->set_node(1) = _mesh->node_ptr(1); elem_top->set_node(2) = _mesh->node_ptr(2); elem_top->set_node(3) = _mesh->node_ptr(3); Elem* elem_bottom = _mesh->add_elem( new Quad4 ); elem_bottom->set_node(0) = _mesh->node_ptr(4); elem_bottom->set_node(1) = _mesh->node_ptr(5); elem_bottom->set_node(2) = _mesh->node_ptr(1); elem_bottom->set_node(3) = _mesh->node_ptr(0); Elem* edge = _mesh->add_elem( new Edge2 ); edge->set_node(0) = _mesh->node_ptr(0); edge->set_node(1) = _mesh->node_ptr(1); // 2D elements will have subdomain id 0, this one will have 1 edge->subdomain_id() = 1; } // libMesh will renumber, but we numbered according to its scheme // anyway. We do this because when we call uniformly_refine subsequenly, // it's going use skip_renumber=false. _mesh->prepare_for_use(false /*skip_renumber*/); }
UniquePtr<Elem> Tri3::build_side (const unsigned int i, bool proxy) const { libmesh_assert_less (i, this->n_sides()); if (proxy) return UniquePtr<Elem>(new Side<Edge2,Tri3>(this,i)); else { Elem* edge = new Edge2; edge->subdomain_id() = this->subdomain_id(); switch (i) { case 0: { edge->set_node(0) = this->get_node(0); edge->set_node(1) = this->get_node(1); break; } case 1: { edge->set_node(0) = this->get_node(1); edge->set_node(1) = this->get_node(2); break; } case 2: { edge->set_node(0) = this->get_node(2); edge->set_node(1) = this->get_node(0); break; } default: libmesh_error_msg("Invalid side i = " << i); } return UniquePtr<Elem>(edge); } libmesh_error_msg("We'll never get here!"); return UniquePtr<Elem>(); }
UniquePtr<Elem> Hex::side (const unsigned int i) const { libmesh_assert_less (i, this->n_sides()); Elem * face = new Quad4; for (unsigned n=0; n<face->n_nodes(); ++n) face->set_node(n) = this->get_node(Hex8::side_nodes_map[i][n]); return UniquePtr<Elem>(face); }
UniquePtr<Elem> Tet::side_ptr (const unsigned int i) { libmesh_assert_less (i, this->n_sides()); Elem * face = new Tri3; for (unsigned n=0; n<face->n_nodes(); ++n) face->set_node(n) = this->node_ptr(Tet4::side_nodes_map[i][n]); return UniquePtr<Elem>(face); }
UniquePtr<Elem> Tri::side (const unsigned int i) const { libmesh_assert_less (i, this->n_sides()); Elem* edge = new Edge2; for (unsigned n=0; n<edge->n_nodes(); ++n) edge->set_node(n) = this->get_node(Tri3::side_nodes_map[i][n]); return UniquePtr<Elem>(edge); }
UniquePtr<Elem> InfHex::side (const unsigned int i) const { libmesh_assert_less (i, this->n_sides()); // To be returned wrapped in a UniquePtr Elem * face = libmesh_nullptr; // Think of a unit cube: (-1,1) x (-1,1) x (-1,1), // with (in general) the normals pointing outwards switch (i) { // the face at z = -1 // the base, where the infinite element couples to conventional // elements case 0: { // Oops, here we are, claiming the normal of the face // elements point outwards -- and this is the exception: // For the side built from the base face, // the normal is pointing _into_ the element! // Why is that? - In agreement with build_side(), // which in turn _has_ to build the face in this // way as to enable the cool way \p InfFE re-uses \p FE. face = new Quad4; break; } // These faces connect to other infinite elements. case 1: // the face at y = -1 case 2: // the face at x = 1 case 3: // the face at y = 1 case 4: // the face at x = -1 { face = new InfQuad4; break; } default: libmesh_error_msg("Invalid side i = " << i); } // Set the nodes for (unsigned n=0; n<face->n_nodes(); ++n) face->set_node(n) = this->node_ptr(InfHex8::side_nodes_map[i][n]); return UniquePtr<Elem>(face); }
UniquePtr<Elem> Tet::side (const unsigned int i) const { libmesh_assert_less (i, this->n_sides()); Elem* face = new Tri3; switch (i) { case 0: { face->set_node(0) = this->get_node(0); face->set_node(1) = this->get_node(2); face->set_node(2) = this->get_node(1); break; } case 1: { face->set_node(0) = this->get_node(0); face->set_node(1) = this->get_node(1); face->set_node(2) = this->get_node(3); break; } case 2: { face->set_node(0) = this->get_node(1); face->set_node(1) = this->get_node(2); face->set_node(2) = this->get_node(3); break; } case 3: { face->set_node(0) = this->get_node(2); face->set_node(1) = this->get_node(0); face->set_node(2) = this->get_node(3); break; } default: libmesh_error_msg("Invalid side i = " << i); } return UniquePtr<Elem>(face); }
void testPostInitAddElem() { ReplicatedMesh mesh(*TestCommWorld); EquationSystems es(mesh); System &sys = es.add_system<System> ("SimpleSystem"); sys.add_variable("u", FIRST); MeshTools::Generation::build_line (mesh, 10, 0., 1., EDGE2); es.init(); Elem* e = Elem::build(EDGE2).release(); e->set_id(mesh.max_elem_id()); e->processor_id() = 0; e->set_node(0) = mesh.node_ptr(2); e->set_node(1) = mesh.node_ptr(8); mesh.add_elem(e); mesh.prepare_for_use(); es.reinit(); }
UniquePtr<Elem> Tet10::build_side (const unsigned int i, bool proxy) const { libmesh_assert_less (i, this->n_sides()); if (proxy) return UniquePtr<Elem>(new Side<Tri6,Tet10>(this,i)); else { Elem * face = new Tri6; face->subdomain_id() = this->subdomain_id(); for (unsigned n=0; n<face->n_nodes(); ++n) face->set_node(n) = this->get_node(Tet10::side_nodes_map[i][n]); return UniquePtr<Elem>(face); } libmesh_error_msg("We'll never get here!"); return UniquePtr<Elem>(); }
UniquePtr<Elem> Tri6::build_side (const unsigned int i, bool proxy) const { libmesh_assert_less (i, this->n_sides()); if (proxy) return UniquePtr<Elem>(new Side<Edge3,Tri6>(this,i)); else { Elem* edge = new Edge3; edge->subdomain_id() = this->subdomain_id(); // Set the nodes for (unsigned n=0; n<edge->n_nodes(); ++n) edge->set_node(n) = this->get_node(Tri6::side_nodes_map[i][n]); return UniquePtr<Elem>(edge); } libmesh_error_msg("We'll never get here!"); return UniquePtr<Elem>(); }
void OFFIO::read_stream(std::istream& in) { // This is a serial-only process for now; // the Mesh should be read on processor 0 and // broadcast later libmesh_assert_equal_to (this->mesh().processor_id(), 0); // Get a reference to the mesh MeshBase& the_mesh = MeshInput<MeshBase>::mesh(); // Clear any existing mesh data the_mesh.clear(); // Check the input buffer libmesh_assert (in.good()); unsigned int nn, ne, nf; std::string label; // Read the first string. It should say "OFF" in >> label; libmesh_assert_equal_to (label, "OFF"); // read the number of nodes, faces, and edges in >> nn >> nf >> ne; Real x=0., y=0., z=0.; // Read the nodes for (unsigned int n=0; n<nn; n++) { libmesh_assert (in.good()); in >> x >> y >> z; the_mesh.add_point ( Point(x,y,z), n ); } unsigned int nv, nid; // Read the elements for (unsigned int e=0; e<nf; e++) { libmesh_assert (in.good()); // The number of vertices in the element in >> nv; libmesh_assert(nv == 2 || nv == 3); if (e == 0) { the_mesh.set_mesh_dimension(nv-1); if (nv == 3) { #if LIBMESH_DIM < 2 libMesh::err << "Cannot open dimension 2 mesh file when configured without 2D support." << std::endl; libmesh_error(); #endif } } Elem* elem; switch (nv) { case 2: elem = new Edge2; break; case 3: elem = new Tri3 ; break; default: libmesh_error(); } elem->set_id(e); the_mesh.add_elem (elem); for (unsigned int i=0; i<nv; i++) { in >> nid; elem->set_node(i) = the_mesh.node_ptr(nid); } } }
std::unique_ptr<MeshBase> SpiralAnnularMeshGenerator::generate() { std::unique_ptr<ReplicatedMesh> mesh = libmesh_make_unique<ReplicatedMesh>(comm(), 2); { // Compute the radial bias given: // .) the inner radius // .) the outer radius // .) the initial_delta_r // .) the desired number of intervals // Note: the exponent n used in the formula is one less than the // number of rings the user requests. Real alpha = 1.1; int n = _num_rings - 1; // lambda used to compute the residual and Jacobian for the Newton iterations. // We capture parameters which don't need to change from the current scope at // the time this lambda is declared. The values are not updated later, so we // can't use this for e.g. f, df, and alpha. auto newton = [this, n](Real & f, Real & df, const Real & alpha) { f = (1. - std::pow(alpha, n + 1)) / (1. - alpha) - (_outer_radius - _inner_radius) / _initial_delta_r; df = (-(n + 1) * (1 - alpha) * std::pow(alpha, n) + (1. - std::pow(alpha, n + 1))) / (1. - alpha) / (1. - alpha); }; Real f, df; int num_iter = 1; newton(f, df, alpha); while (std::abs(f) > 1.e-9 && num_iter <= 25) { // Compute and apply update. Real dx = -f / df; alpha += dx; newton(f, df, alpha); num_iter++; } // In case the Newton iteration fails to converge. if (num_iter > 25) mooseError("Newton iteration failed to converge (more than 25 iterations)."); // Set radial basis to the value of alpha that we computed with Newton. _radial_bias = alpha; } // The number of rings specified by the user does not include the ring at // the surface of the cylinder itself, so we increment it by one now. _num_rings += 1; // Data structure that holds pointers to the Nodes of each ring. std::vector<std::vector<Node *>> ring_nodes(_num_rings); // Initialize radius and delta_r variables. Real radius = _inner_radius; Real delta_r = _initial_delta_r; // Node id counter. unsigned int current_node_id = 0; for (std::size_t r = 0; r < _num_rings; ++r) { ring_nodes[r].resize(_nodes_per_ring); // Add nodes starting from either theta=0 or theta=pi/nodes_per_ring Real theta = r % 2 == 0 ? 0 : (libMesh::pi / _nodes_per_ring); for (std::size_t n = 0; n < _nodes_per_ring; ++n) { ring_nodes[r][n] = mesh->add_point(Point(radius * std::cos(theta), radius * std::sin(theta)), current_node_id++); // Update angle theta += 2 * libMesh::pi / _nodes_per_ring; } // Go to next ring radius += delta_r; delta_r *= _radial_bias; } // Add elements for (std::size_t r = 0; r < _num_rings - 1; ++r) { // even -> odd ring if (r % 2 == 0) { // Inner ring (n, n*, n+1) // Starred indices refer to nodes on the "outer" ring of this pair. for (std::size_t n = 0; n < _nodes_per_ring; ++n) { // Wrap around unsigned int np1 = (n == _nodes_per_ring - 1) ? 0 : n + 1; Elem * elem = mesh->add_elem(new Tri3); elem->set_node(0) = ring_nodes[r][n]; elem->set_node(1) = ring_nodes[r + 1][n]; elem->set_node(2) = ring_nodes[r][np1]; // Add interior faces to 'cylinder' sideset if we are on ring 0. if (r == 0) mesh->boundary_info->add_side(elem->id(), /*side=*/2, _cylinder_bid); } // Outer ring (n*, n+1*, n+1) for (std::size_t n = 0; n < _nodes_per_ring; ++n) { // Wrap around unsigned int np1 = (n == _nodes_per_ring - 1) ? 0 : n + 1; Elem * elem = mesh->add_elem(new Tri3); elem->set_node(0) = ring_nodes[r + 1][n]; elem->set_node(1) = ring_nodes[r + 1][np1]; elem->set_node(2) = ring_nodes[r][np1]; // Add exterior faces to 'exterior' sideset if we're on the last ring. // Note: this code appears in two places since we could end on either an even or odd ring. if (r == _num_rings - 2) mesh->boundary_info->add_side(elem->id(), /*side=*/0, _exterior_bid); } } else { // odd -> even ring // Inner ring (n, n+1*, n+1) for (std::size_t n = 0; n < _nodes_per_ring; ++n) { // Wrap around unsigned int np1 = (n == _nodes_per_ring - 1) ? 0 : n + 1; Elem * elem = mesh->add_elem(new Tri3); elem->set_node(0) = ring_nodes[r][n]; elem->set_node(1) = ring_nodes[r + 1][np1]; elem->set_node(2) = ring_nodes[r][np1]; } // Outer ring (n*, n+1*, n) for (std::size_t n = 0; n < _nodes_per_ring; ++n) { // Wrap around unsigned int np1 = (n == _nodes_per_ring - 1) ? 0 : n + 1; Elem * elem = mesh->add_elem(new Tri3); elem->set_node(0) = ring_nodes[r + 1][n]; elem->set_node(1) = ring_nodes[r + 1][np1]; elem->set_node(2) = ring_nodes[r][n]; // Add exterior faces to 'exterior' sideset if we're on the last ring. if (r == _num_rings - 2) mesh->boundary_info->add_side(elem->id(), /*side=*/0, _exterior_bid); } } } // Sanity check: make sure all elements have positive area. Note: we // can't use elem->volume() for this, as that always returns a // positive area regardless of the node ordering. // We compute (p1-p0) \cross (p2-p0) and check that the z-component is positive. for (const auto & elem : mesh->element_ptr_range()) { Point cp = (elem->point(1) - elem->point(0)).cross(elem->point(2) - elem->point(0)); if (cp(2) < 0.) mooseError("Invalid elem found with negative area"); } // Create sideset names. mesh->boundary_info->sideset_name(_cylinder_bid) = "cylinder"; mesh->boundary_info->sideset_name(_exterior_bid) = "exterior"; // Find neighbors, etc. mesh->prepare_for_use(); if (_use_tri6) { mesh->all_second_order(/*full_ordered=*/true); std::vector<unsigned int> nos; // Loop over the elements, moving mid-edge nodes onto the // nearest radius as applicable. For each element, exactly one // edge should lie on the same radius, so we move only that // mid-edge node. for (const auto & elem : mesh->element_ptr_range()) { // Make sure we are dealing only with triangles libmesh_assert(elem->n_vertices() == 3); // Compute vertex radii Real radii[3] = {elem->point(0).norm(), elem->point(1).norm(), elem->point(2).norm()}; // Compute absolute differences between radii so we can determine which two are on the same // circular arc. Real dr[3] = {std::abs(radii[0] - radii[1]), std::abs(radii[1] - radii[2]), std::abs(radii[2] - radii[0])}; // Compute index of minimum dr. auto index = std::distance(std::begin(dr), std::min_element(std::begin(dr), std::end(dr))); // Make sure that the minimum found is also (almost) zero. if (dr[index] > TOLERANCE) mooseError("Error: element had no sides with nodes on same radius."); // Get list of all local node ids on this side. The first // two entries in nos correspond to the vertices, the last // entry corresponds to the mid-edge node. nos = elem->nodes_on_side(index); // Compute the angles associated with nodes nos[0] and nos[1]. Real theta0 = std::atan2(elem->point(nos[0])(1), elem->point(nos[0])(0)), theta1 = std::atan2(elem->point(nos[1])(1), elem->point(nos[1])(0)); // atan2 returns values in the range (-pi, pi). If theta0 // and theta1 have the same sign, we can simply average them // to get half of the acute angle between them. On the other // hand, if theta0 and theta1 are of opposite sign _and_ both // are larger than pi/2, we need to add 2*pi when averaging, // otherwise we will get half of the _obtuse_ angle between // them, and the point will flip to the other side of the // circle (see below). Real new_theta = 0.5 * (theta0 + theta1); // It should not be possible for both: // 1.) |theta0| > pi/2, and // 2.) |theta1| < pi/2 // as this would not be a well-formed element. if ((theta0 * theta1 < 0) && (std::abs(theta0) > 0.5 * libMesh::pi) && (std::abs(theta1) > 0.5 * libMesh::pi)) new_theta = 0.5 * (theta0 + theta1 + 2 * libMesh::pi); // The new radius will be the radius of point nos[0] or nos[1] (they are the same!). Real new_r = elem->point(nos[0]).norm(); // Finally, move the point to its new location. elem->point(nos[2]) = Point(new_r * std::cos(new_theta), new_r * std::sin(new_theta), 0.); } } return dynamic_pointer_cast<MeshBase>(mesh); }
UniquePtr<Elem> InfPrism12::build_side_ptr (const unsigned int i, bool proxy) { libmesh_assert_less (i, this->n_sides()); if (proxy) { switch (i) { // base case 0: return UniquePtr<Elem>(new Side<Tri6,InfPrism12>(this,i)); // ifem sides case 1: case 2: case 3: return UniquePtr<Elem>(new Side<InfQuad6,InfPrism12>(this,i)); default: libmesh_error_msg("Invalid side i = " << i); } } else { // Create NULL pointer to be initialized, returned later. Elem * face = libmesh_nullptr; switch (i) { case 0: // the triangular face at z=-1, base face { face = new Tri6; break; } case 1: // the quad face at y=0 case 2: // the other quad face case 3: // the quad face at x=0 { face = new InfQuad6; break; } default: libmesh_error_msg("Invalid side i = " << i); } face->subdomain_id() = this->subdomain_id(); // Set the nodes for (unsigned n=0; n<face->n_nodes(); ++n) face->set_node(n) = this->node_ptr(InfPrism12::side_nodes_map[i][n]); return UniquePtr<Elem>(face); } libmesh_error_msg("We'll never get here!"); return UniquePtr<Elem>(); }
void AnnularMesh::buildMesh() { const Real dt = (_tmax - _tmin) / _nt; MeshBase & mesh = getMesh(); mesh.clear(); mesh.set_mesh_dimension(2); mesh.set_spatial_dimension(2); BoundaryInfo & boundary_info = mesh.get_boundary_info(); const unsigned num_angular_nodes = (_full_annulus ? _nt : _nt + 1); const unsigned num_nodes = (_rmin > 0.0 ? (_nr + 1) * num_angular_nodes : _nr * num_angular_nodes + 1); const unsigned min_nonzero_layer_num = (_rmin > 0.0 ? 0 : 1); std::vector<Node *> nodes(num_nodes); unsigned node_id = 0; // add nodes at rmax that aren't yet connected to any elements Real current_r = _rmax; for (unsigned angle_num = 0; angle_num < num_angular_nodes; ++angle_num) { const Real angle = _tmin + angle_num * dt; const Real x = current_r * std::cos(angle); const Real y = current_r * std::sin(angle); nodes[node_id] = mesh.add_point(Point(x, y, 0.0), node_id); node_id++; } // add nodes at smaller radii, and connect them with elements for (unsigned layer_num = _nr; layer_num > min_nonzero_layer_num; --layer_num) { if (layer_num == 1) current_r = _rmin; // account for precision loss else current_r -= _len * std::pow(_growth_r, layer_num - 1); // add node at angle = _tmin nodes[node_id] = mesh.add_point( Point(current_r * std::cos(_tmin), current_r * std::sin(_tmin), 0.0), node_id); node_id++; for (unsigned angle_num = 1; angle_num < num_angular_nodes; ++angle_num) { const Real angle = _tmin + angle_num * dt; const Real x = current_r * std::cos(angle); const Real y = current_r * std::sin(angle); nodes[node_id] = mesh.add_point(Point(x, y, 0.0), node_id); Elem * elem = mesh.add_elem(new Quad4); elem->set_node(0) = nodes[node_id]; elem->set_node(1) = nodes[node_id - 1]; elem->set_node(2) = nodes[node_id - num_angular_nodes - 1]; elem->set_node(3) = nodes[node_id - num_angular_nodes]; elem->subdomain_id() = _quad_subdomain_id; node_id++; if (layer_num == _nr) // add outer boundary (boundary_id = 1) boundary_info.add_side(elem, 2, 1); if (layer_num == 1) // add inner boundary (boundary_id = 0) boundary_info.add_side(elem, 0, 0); if (!_full_annulus && angle_num == 1) // add tmin boundary (boundary_id = 2) boundary_info.add_side(elem, 1, 2); if (!_full_annulus && angle_num == num_angular_nodes - 1) // add tmin boundary (boundary_id = 3) boundary_info.add_side(elem, 3, 3); } if (_full_annulus) { // add element connecting to node at angle=0 Elem * elem = mesh.add_elem(new Quad4); elem->set_node(0) = nodes[node_id - num_angular_nodes]; elem->set_node(1) = nodes[node_id - 1]; elem->set_node(2) = nodes[node_id - num_angular_nodes - 1]; elem->set_node(3) = nodes[node_id - 2 * num_angular_nodes]; elem->subdomain_id() = _quad_subdomain_id; if (layer_num == _nr) // add outer boundary (boundary_id = 1) boundary_info.add_side(elem, 2, 1); if (layer_num == 1) // add inner boundary (boundary_id = 0) boundary_info.add_side(elem, 0, 0); } } // add single node at origin, if relevant if (_rmin == 0.0) { nodes[node_id] = mesh.add_point(Point(0.0, 0.0, 0.0), node_id); boundary_info.add_node(node_id, 0); // boundary_id=0 is centre for (unsigned angle_num = 0; angle_num < num_angular_nodes - 1; ++angle_num) { Elem * elem = mesh.add_elem(new Tri3); elem->set_node(0) = nodes[node_id]; elem->set_node(1) = nodes[node_id - num_angular_nodes + angle_num]; elem->set_node(2) = nodes[node_id - num_angular_nodes + angle_num + 1]; elem->subdomain_id() = _tri_subdomain_id; } if (_full_annulus) { Elem * elem = mesh.add_elem(new Tri3); elem->set_node(0) = nodes[node_id]; elem->set_node(1) = nodes[node_id - 1]; elem->set_node(2) = nodes[node_id - num_angular_nodes]; elem->subdomain_id() = _tri_subdomain_id; } } boundary_info.sideset_name(0) = "rmin"; boundary_info.sideset_name(1) = "rmax"; boundary_info.nodeset_name(0) = "rmin"; boundary_info.nodeset_name(1) = "rmax"; if (!_full_annulus) { boundary_info.sideset_name(2) = "tmin"; boundary_info.sideset_name(3) = "tmax"; boundary_info.nodeset_name(2) = "tmin"; boundary_info.nodeset_name(3) = "tmax"; } mesh.prepare_for_use(false); }
void MatlabIO::read_stream(std::istream& in) { // This is a serial-only process for now; // the Mesh should be read on processor 0 and // broadcast later libmesh_assert_equal_to (this->mesh().processor_id(), 0); // Get a reference to the mesh MeshBase& the_mesh = MeshInput<MeshBase>::mesh(); // Clear any existing mesh data the_mesh.clear(); // PDE toolkit only works in 2D the_mesh.set_mesh_dimension(2); #if LIBMESH_DIM < 2 libMesh::err << "Cannot open dimension 2 mesh file when configured without 2D support." << std::endl; libmesh_error(); #endif // Check the input buffer libmesh_assert (in.good()); unsigned int nNodes=0, nElem=0; in >> nNodes // Read the number of nodes >> nElem; // Read the number of elements // Sort of check that it worked libmesh_assert_greater (nNodes, 0); libmesh_assert_greater (nElem, 0); // Read the nodal coordinates { Real x=0., y=0., z=0.; for (unsigned int i=0; i<nNodes; i++) { in >> x // x-coordinate value >> y; // y-coordinate value the_mesh.add_point ( Point(x,y,z), i); } } // Read the elements (elements) { unsigned int node=0, dummy=0; for (unsigned int i=0; i<nElem; i++) { Elem* elem = new Tri3; // Always build a triangle elem->set_id(i); the_mesh.add_elem (elem); for (unsigned int n=0; n<3; n++) // Always read three 3 nodes { in >> node; elem->set_node(n) = the_mesh.node_ptr(node-1); // Assign the node number } // There is an additional subdomain number here, // so we read it and get rid of it! in >> dummy; } } }
void ExodusII_IO::read (const std::string& fname) { // This is a serial-only process for now; // the Mesh should be read on processor 0 and // broadcast later // libmesh_assert_equal_to (libMesh::processor_id(), 0); #ifndef LIBMESH_HAVE_EXODUS_API libMesh::err << "ERROR, ExodusII API is not defined.\n" << "Input file " << fname << " cannot be read" << std::endl; libmesh_error(); #else // Get a reference to the mesh we are reading MeshBase& mesh = MeshInput<MeshBase>::mesh(); // Clear any existing mesh data mesh.clear(); // Keep track of what kinds of elements this file contains elems_of_dimension.clear(); elems_of_dimension.resize(4, false); #ifdef DEBUG this->verbose(true); #endif ExodusII_IO_Helper::ElementMaps em; // Instantiate the ElementMaps interface exio_helper->open(fname.c_str()); // Open the exodus file, if possible exio_helper->read_header(); // Get header information from exodus file exio_helper->print_header(); // Print header information //assertion fails due to inconsistent mesh dimension // libmesh_assert_equal_to (static_cast<unsigned int>(exio_helper->get_num_dim()), mesh.mesh_dimension()); // Be sure number of dimensions // is equal to the number of // dimensions in the mesh supplied. exio_helper->read_nodes(); // Read nodes from the exodus file mesh.reserve_nodes(exio_helper->get_num_nodes()); // Reserve space for the nodes. // Loop over the nodes, create Nodes with local processor_id 0. for (int i=0; i<exio_helper->get_num_nodes(); i++) mesh.add_point (Point(exio_helper->get_x(i), exio_helper->get_y(i), exio_helper->get_z(i)), i); libmesh_assert_equal_to (static_cast<unsigned int>(exio_helper->get_num_nodes()), mesh.n_nodes()); exio_helper->read_block_info(); // Get information about all the blocks mesh.reserve_elem(exio_helper->get_num_elem()); // Reserve space for the elements // Read in the element connectivity for each block. int nelem_last_block = 0; std::map<int, unsigned int> exodus_id_to_mesh_id; // Loop over all the blocks for (int i=0; i<exio_helper->get_num_elem_blk(); i++) { // Read the information for block i exio_helper->read_elem_in_block (i); int subdomain_id = exio_helper->get_block_id(i); // populate the map of names mesh.subdomain_name(static_cast<subdomain_id_type>(subdomain_id)) = exio_helper->get_block_name(i); // Set any relevant node/edge maps for this element const std::string type_str (exio_helper->get_elem_type()); const ExodusII_IO_Helper::Conversion conv = em.assign_conversion(type_str); //if (_verbose) //libMesh::out << "Reading a block of " << type_str << " elements." << std::endl; // Loop over all the faces in this block int jmax = nelem_last_block+exio_helper->get_num_elem_this_blk(); for (int j=nelem_last_block; j<jmax; j++) { Elem* elem = Elem::build (conv.get_canonical_type()).release(); libmesh_assert (elem); elem->subdomain_id() = static_cast<subdomain_id_type>(subdomain_id) ; //elem->set_id(j);// Don't try to second guess the Element ID setting scheme! elems_of_dimension[elem->dim()] = true; elem = mesh.add_elem (elem); // Catch the Elem pointer that the Mesh throws back exodus_id_to_mesh_id[j+1] = elem->id(); // Set all the nodes for this element for (int k=0; k<exio_helper->get_num_nodes_per_elem(); k++) { int gi = (j-nelem_last_block)*exio_helper->get_num_nodes_per_elem() + conv.get_node_map(k); // global index int node_number = exio_helper->get_connect(gi); // Global node number (1-based) elem->set_node(k) = mesh.node_ptr((node_number-1)); // Set node number // Subtract 1 since // exodus is internally 1-based } } // running sum of # of elements per block, // (should equal total number of elements in the end) nelem_last_block += exio_helper->get_num_elem_this_blk(); } libmesh_assert_equal_to (static_cast<unsigned int>(nelem_last_block), mesh.n_elem()); // Set the mesh dimension to the largest encountered for an element for (unsigned int i=0; i!=4; ++i) if (elems_of_dimension[i]) mesh.set_mesh_dimension(i); // Read in sideset information -- this is useful for applying boundary conditions { exio_helper->read_sideset_info(); // Get basic information about ALL sidesets int offset=0; for (int i=0; i<exio_helper->get_num_side_sets(); i++) { offset += (i > 0 ? exio_helper->get_num_sides_per_set(i-1) : 0); // Compute new offset exio_helper->read_sideset (i, offset); mesh.boundary_info->sideset_name(exio_helper->get_side_set_id(i)) = exio_helper->get_side_set_name(i); } const std::vector<int>& elem_list = exio_helper->get_elem_list(); const std::vector<int>& side_list = exio_helper->get_side_list(); const std::vector<int>& id_list = exio_helper->get_id_list(); for (unsigned int e=0; e<elem_list.size(); e++) { // Set any relevant node/edge maps for this element Elem * elem = mesh.elem(exodus_id_to_mesh_id[elem_list[e]]); const ExodusII_IO_Helper::Conversion conv = em.assign_conversion(elem->type()); mesh.boundary_info->add_side (exodus_id_to_mesh_id[elem_list[e]], conv.get_side_map(side_list[e]-1), id_list[e]); } } // Read nodeset info { exio_helper->read_nodeset_info(); for (int nodeset=0; nodeset<exio_helper->get_num_node_sets(); nodeset++) { int nodeset_id = exio_helper->get_nodeset_id(nodeset); mesh.boundary_info->nodeset_name(nodeset_id) = exio_helper->get_node_set_name(nodeset); exio_helper->read_nodeset(nodeset); const std::vector<int>& node_list = exio_helper->get_node_list(); for(unsigned int node=0; node<node_list.size(); node++) mesh.boundary_info->add_node(node_list[node]-1, nodeset_id); } } #if LIBMESH_DIM < 3 if (mesh.mesh_dimension() > LIBMESH_DIM) { libMesh::err << "Cannot open dimension " << mesh.mesh_dimension() << " mesh file when configured without " << mesh.mesh_dimension() << "D support." << std::endl; libmesh_error(); } #endif #endif }
UniquePtr<Elem> Prism::side (const unsigned int i) const { libmesh_assert_less (i, this->n_sides()); Elem* face = NULL; switch (i) { case 0: // the triangular face at z=0 { face = new Tri3; face->set_node(0) = this->get_node(0); face->set_node(1) = this->get_node(2); face->set_node(2) = this->get_node(1); break; } case 1: // the quad face at y=0 { face = new Quad4; face->set_node(0) = this->get_node(0); face->set_node(1) = this->get_node(1); face->set_node(2) = this->get_node(4); face->set_node(3) = this->get_node(3); break; } case 2: // the other quad face { face = new Quad4; face->set_node(0) = this->get_node(1); face->set_node(1) = this->get_node(2); face->set_node(2) = this->get_node(5); face->set_node(3) = this->get_node(4); break; } case 3: // the quad face at x=0 { face = new Quad4; face->set_node(0) = this->get_node(2); face->set_node(1) = this->get_node(0); face->set_node(2) = this->get_node(3); face->set_node(3) = this->get_node(5); break; } case 4: // the triangular face at z=1 { face = new Tri3; face->set_node(0) = this->get_node(3); face->set_node(1) = this->get_node(4); face->set_node(2) = this->get_node(5); break; } default: libmesh_error_msg("Invalid side i = " << i); } return UniquePtr<Elem>(face); }
void TriangleWrapper::copy_tri_to_mesh(const triangulateio& triangle_data_input, UnstructuredMesh& mesh_output, const ElemType type) { // Transfer the information into the LibMesh mesh. mesh_output.clear(); // Make sure the new Mesh will be 2D mesh_output.set_mesh_dimension(2); // Node information for (int i=0, c=0; c<triangle_data_input.numberofpoints; i+=2, ++c) { // Specify ID when adding point, otherwise, if this is ParallelMesh, // it might add points with a non-sequential numbering... mesh_output.add_point( Point(triangle_data_input.pointlist[i], triangle_data_input.pointlist[i+1]), /*id=*/c); } // Element information for (int i=0; i<triangle_data_input.numberoftriangles; ++i) { switch (type) { case TRI3: { Elem* elem = mesh_output.add_elem (new Tri3); for (unsigned int n=0; n<3; ++n) elem->set_node(n) = mesh_output.node_ptr(triangle_data_input.trianglelist[i*3 + n]); break; } case TRI6: { Elem* elem = mesh_output.add_elem (new Tri6); // Triangle number TRI6 nodes in a different way to libMesh elem->set_node(0) = mesh_output.node_ptr(triangle_data_input.trianglelist[i*6 + 0]); elem->set_node(1) = mesh_output.node_ptr(triangle_data_input.trianglelist[i*6 + 1]); elem->set_node(2) = mesh_output.node_ptr(triangle_data_input.trianglelist[i*6 + 2]); elem->set_node(3) = mesh_output.node_ptr(triangle_data_input.trianglelist[i*6 + 5]); elem->set_node(4) = mesh_output.node_ptr(triangle_data_input.trianglelist[i*6 + 3]); elem->set_node(5) = mesh_output.node_ptr(triangle_data_input.trianglelist[i*6 + 4]); break; } default: { libMesh::err << "ERROR: Unrecognized triangular element type." << std::endl; libmesh_error(); } } } // Note: If the input mesh was a parallel one, calling // prepare_for_use() now will re-parallelize it by a call to // delete_remote_elements()... We do not actually want to // reparallelize it here though: the triangulate() function may // still do some Mesh smoothing. The main thing needed (for // smoothing) is the neighbor information, so let's just find // neighbors... //mesh_output.prepare_for_use(/*skip_renumber =*/false); mesh_output.find_neighbors(); }
void VTKIO::read (const std::string& name) { // This is a serial-only process for now; // the Mesh should be read on processor 0 and // broadcast later libmesh_assert_equal_to (MeshOutput<MeshBase>::mesh().processor_id(), 0); // Keep track of what kinds of elements this file contains elems_of_dimension.clear(); elems_of_dimension.resize(4, false); #ifndef LIBMESH_HAVE_VTK libMesh::err << "Cannot read VTK file: " << name << "\nYou must have VTK installed and correctly configured to read VTK meshes." << std::endl; libmesh_error(); #else // Use a typedef, because these names are just crazy typedef vtkSmartPointer<vtkXMLUnstructuredGridReader> MyReader; MyReader reader = MyReader::New(); // Pass the filename along to the reader reader->SetFileName( name.c_str() ); // Force reading reader->Update(); // read in the grid _vtk_grid = reader->GetOutput(); // _vtk_grid->Update(); // FIXME: Necessary? // Get a reference to the mesh MeshBase& mesh = MeshInput<MeshBase>::mesh(); // Clear out any pre-existing data from the Mesh mesh.clear(); // Get the number of points from the _vtk_grid object const unsigned int vtk_num_points = static_cast<unsigned int>(_vtk_grid->GetNumberOfPoints()); // always numbered nicely??, so we can loop like this // I'm pretty sure it is numbered nicely for (unsigned int i=0; i<vtk_num_points; ++i) { // add to the id map // and add the actual point double * pnt = _vtk_grid->GetPoint(static_cast<vtkIdType>(i)); Point xyz(pnt[0], pnt[1], pnt[2]); Node* newnode = mesh.add_point(xyz, i); // Add node to the nodes vector & // tell the MeshData object the foreign node id. if (this->_mesh_data != NULL) this->_mesh_data->add_foreign_node_id (newnode, i); } // Get the number of cells from the _vtk_grid object const unsigned int vtk_num_cells = static_cast<unsigned int>(_vtk_grid->GetNumberOfCells()); for (unsigned int i=0; i<vtk_num_cells; ++i) { vtkCell* cell = _vtk_grid->GetCell(i); Elem* elem = NULL; switch (cell->GetCellType()) { case VTK_LINE: elem = new Edge2; break; case VTK_QUADRATIC_EDGE: elem = new Edge3; break; case VTK_TRIANGLE: elem = new Tri3(); break; case VTK_QUADRATIC_TRIANGLE: elem = new Tri6(); break; case VTK_QUAD: elem = new Quad4(); break; case VTK_QUADRATIC_QUAD: elem = new Quad8(); break; #if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0) case VTK_BIQUADRATIC_QUAD: elem = new Quad9(); break; #endif case VTK_TETRA: elem = new Tet4(); break; case VTK_QUADRATIC_TETRA: elem = new Tet10(); break; case VTK_WEDGE: elem = new Prism6(); break; case VTK_QUADRATIC_WEDGE: elem = new Prism15(); break; case VTK_BIQUADRATIC_QUADRATIC_WEDGE: elem = new Prism18(); break; case VTK_HEXAHEDRON: elem = new Hex8(); break; case VTK_QUADRATIC_HEXAHEDRON: elem = new Hex20(); break; case VTK_TRIQUADRATIC_HEXAHEDRON: elem = new Hex27(); break; case VTK_PYRAMID: elem = new Pyramid5(); break; default: libMesh::err << "element type not implemented in vtkinterface " << cell->GetCellType() << std::endl; libmesh_error(); break; } // get the straightforward numbering from the VTK cells for (unsigned int j=0; j<elem->n_nodes(); ++j) elem->set_node(j) = mesh.node_ptr(cell->GetPointId(j)); // then get the connectivity std::vector<dof_id_type> conn; elem->connectivity(0, VTK, conn); // then reshuffle the nodes according to the connectivity, this // two-time-assign would evade the definition of the vtk_mapping for (unsigned int j=0; j<conn.size(); ++j) elem->set_node(j) = mesh.node_ptr(conn[j]); elem->set_id(i); elems_of_dimension[elem->dim()] = true; mesh.add_elem(elem); } // end loop over VTK cells // Set the mesh dimension to the largest encountered for an element for (unsigned int i=0; i!=4; ++i) if (elems_of_dimension[i]) mesh.set_mesh_dimension(i); #if LIBMESH_DIM < 3 if (mesh.mesh_dimension() > LIBMESH_DIM) { libMesh::err << "Cannot open dimension " << mesh.mesh_dimension() << " mesh file when configured without " << mesh.mesh_dimension() << "D support." << std::endl; libmesh_error(); } #endif #endif // LIBMESH_HAVE_VTK }
UniquePtr<Elem> InfHex8::build_side (const unsigned int i, bool proxy) const { libmesh_assert_less (i, this->n_sides()); if (proxy) { switch (i) { // base case 0: return UniquePtr<Elem>(new Side<Quad4,InfHex8>(this,i)); // ifem sides case 1: case 2: case 3: case 4: return UniquePtr<Elem>(new Side<InfQuad4,InfHex8>(this,i)); default: libmesh_error_msg("Invalid side i = " << i); } } else { // Create NULL pointer to be initialized, returned later. Elem* face = NULL; // Think of a unit cube: (-1,1) x (-1,1) x (1,1) switch (i) { case 0: // the base face { face = new Quad4; // Only here, the face element's normal points inward face->set_node(0) = this->get_node(0); face->set_node(1) = this->get_node(1); face->set_node(2) = this->get_node(2); face->set_node(3) = this->get_node(3); break; } case 1: // connecting to another infinite element { face = new InfQuad4; face->set_node(0) = this->get_node(0); face->set_node(1) = this->get_node(1); face->set_node(2) = this->get_node(4); face->set_node(3) = this->get_node(5); break; } case 2: // connecting to another infinite element { face = new InfQuad4; face->set_node(0) = this->get_node(1); face->set_node(1) = this->get_node(2); face->set_node(2) = this->get_node(5); face->set_node(3) = this->get_node(6); break; } case 3: // connecting to another infinite element { face = new InfQuad4; face->set_node(0) = this->get_node(2); face->set_node(1) = this->get_node(3); face->set_node(2) = this->get_node(6); face->set_node(3) = this->get_node(7); break; } case 4: // connecting to another infinite element { face = new InfQuad4; face->set_node(0) = this->get_node(3); face->set_node(1) = this->get_node(0); face->set_node(2) = this->get_node(7); face->set_node(3) = this->get_node(4); break; } default: libmesh_error_msg("Invalid side i = " << i); } face->subdomain_id() = this->subdomain_id(); return UniquePtr<Elem>(face); } libmesh_error_msg("We'll never get here!"); return UniquePtr<Elem>(); }
std::unique_ptr<MeshBase> SphereSurfaceMeshGenerator::generate() { // Have MOOSE construct the correct libMesh::Mesh object using Mesh block and CLI parameters. auto mesh = _mesh->buildMeshBaseObject(); mesh->set_mesh_dimension(2); mesh->set_spatial_dimension(3); const Sphere sphere(_center, _radius); // icosahedron points (using golden ratio rectangle construction) const Real phi = (1.0 + std::sqrt(5.0)) / 2.0; const Real X = std::sqrt(1.0 / (phi * phi + 1.0)); const Real Z = X * phi; const Point vdata[12] = {{-X, 0.0, Z}, {X, 0.0, Z}, {-X, 0.0, -Z}, {X, 0.0, -Z}, {0.0, Z, X}, {0.0, Z, -X}, {0.0, -Z, X}, {0.0, -Z, -X}, {Z, X, 0.0}, {-Z, X, 0.0}, {Z, -X, 0.0}, {-Z, -X, 0.0}}; for (unsigned int i = 0; i < 12; ++i) mesh->add_point(vdata[i] * _radius + _center, i); // icosahedron faces const unsigned int tindices[20][3] = {{0, 4, 1}, {0, 9, 4}, {9, 5, 4}, {4, 5, 8}, {4, 8, 1}, {8, 10, 1}, {8, 3, 10}, {5, 3, 8}, {5, 2, 3}, {2, 7, 3}, {7, 10, 3}, {7, 6, 10}, {7, 11, 6}, {11, 0, 6}, {0, 1, 6}, {6, 1, 10}, {9, 0, 11}, {9, 11, 2}, {9, 2, 5}, {7, 2, 11}}; for (unsigned int i = 0; i < 20; ++i) { Elem * elem = mesh->add_elem(new Tri3); elem->set_node(0) = mesh->node_ptr(tindices[i][0]); elem->set_node(1) = mesh->node_ptr(tindices[i][1]); elem->set_node(2) = mesh->node_ptr(tindices[i][2]); } // we need to prepare distributed meshes before using refinement if (!mesh->is_replicated()) mesh->prepare_for_use(/*skip_renumber =*/false); // Now we have the beginnings of a sphere. // Add some more elements by doing uniform refinements and // popping nodes to the boundary. MeshRefinement mesh_refinement(*mesh); // Loop over the elements, refine, pop nodes to boundary. for (unsigned int r = 0; r < _depth; ++r) { mesh_refinement.uniformly_refine(1); auto it = mesh->active_nodes_begin(); const auto end = mesh->active_nodes_end(); for (; it != end; ++it) { Node & node = **it; node = sphere.closest_point(node); } } // Flatten the AMR mesh to get rid of inactive elements MeshTools::Modification::flatten(*mesh); return dynamic_pointer_cast<MeshBase>(mesh); }
UniquePtr<Elem> InfPrism6::build_side (const unsigned int i, bool proxy) const { libmesh_assert_less (i, this->n_sides()); if (proxy) { switch (i) { // base case 0: return UniquePtr<Elem>(new Side<Tri3,InfPrism6>(this,i)); // ifem sides case 1: case 2: case 3: return UniquePtr<Elem>(new Side<InfQuad4,InfPrism6>(this,i)); default: libmesh_error_msg("Invalid side i = " << i); } } else { // Create NULL pointer to be initialized, returned later. Elem* face = NULL; switch (i) { case 0: // the triangular face at z=-1, base face { face = new Tri3; // Note that for this face element, the normal points inward face->set_node(0) = this->get_node(0); face->set_node(1) = this->get_node(1); face->set_node(2) = this->get_node(2); break; } case 1: // the quad face at y=0 { face = new InfQuad4; face->set_node(0) = this->get_node(0); face->set_node(1) = this->get_node(1); face->set_node(2) = this->get_node(3); face->set_node(3) = this->get_node(4); break; } case 2: // the other quad face { face = new InfQuad4; face->set_node(0) = this->get_node(1); face->set_node(1) = this->get_node(2); face->set_node(2) = this->get_node(4); face->set_node(3) = this->get_node(5); break; } case 3: // the quad face at x=0 { face = new InfQuad4; face->set_node(0) = this->get_node(2); face->set_node(1) = this->get_node(0); face->set_node(2) = this->get_node(5); face->set_node(3) = this->get_node(3); break; } default: libmesh_error_msg("Invalid side i = " << i); } face->subdomain_id() = this->subdomain_id(); return UniquePtr<Elem>(face); } libmesh_error_msg("We'll never get here!"); return UniquePtr<Elem>(); }
void Elem::refine (MeshRefinement& mesh_refinement) { libmesh_assert (this->refinement_flag() == Elem::REFINE); libmesh_assert (this->active()); // Create my children if necessary if (!_children) { _children = new Elem*[this->n_children()]; unsigned int parent_p_level = this->p_level(); for (unsigned int c=0; c<this->n_children(); c++) { _children[c] = Elem::build(this->type(), this).release(); _children[c]->set_refinement_flag(Elem::JUST_REFINED); _children[c]->set_p_level(parent_p_level); _children[c]->set_p_refinement_flag(this->p_refinement_flag()); } // Compute new nodal locations // and asssign nodes to children // Make these static. It is unlikely the // sizes will change from call to call, so having these // static should save on reallocations std::vector<std::vector<Point> > p (this->n_children()); std::vector<std::vector<Node*> > nodes(this->n_children()); // compute new nodal locations for (unsigned int c=0; c<this->n_children(); c++) { Elem *child = this->child(c); p[c].resize (child->n_nodes()); nodes[c].resize(child->n_nodes()); for (unsigned int nc=0; nc<child->n_nodes(); nc++) { // zero entries p[c][nc].zero(); nodes[c][nc] = NULL; for (unsigned int n=0; n<this->n_nodes(); n++) { // The value from the embedding matrix const float em_val = this->embedding_matrix(c,nc,n); if (em_val != 0.) { p[c][nc].add_scaled (this->point(n), em_val); // We may have found the node, in which case we // won't need to look it up later. if (em_val == 1.) nodes[c][nc] = this->get_node(n); } } } // assign nodes to children & add them to the mesh const Real pointtol = this->hmin() * TOLERANCE; for (unsigned int nc=0; nc<child->n_nodes(); nc++) { if (nodes[c][nc] != NULL) { child->set_node(nc) = nodes[c][nc]; } else { child->set_node(nc) = mesh_refinement.add_point(p[c][nc], child->processor_id(), pointtol); child->get_node(nc)->set_n_systems (this->n_systems()); } } mesh_refinement.add_elem (child); child->set_n_systems(this->n_systems()); } } else { unsigned int parent_p_level = this->p_level(); for (unsigned int c=0; c<this->n_children(); c++) { Elem *child = this->child(c); libmesh_assert(child->subactive()); child->set_refinement_flag(Elem::JUST_REFINED); child->set_p_level(parent_p_level); child->set_p_refinement_flag(this->p_refinement_flag()); } } // Un-set my refinement flag now this->set_refinement_flag(Elem::INACTIVE); this->set_p_refinement_flag(Elem::INACTIVE); for (unsigned int c=0; c<this->n_children(); c++) { libmesh_assert(this->child(c)->parent() == this); libmesh_assert(this->child(c)->active()); } libmesh_assert (this->ancestor()); }