void NodeSetTest::test_set_get_clear_simple() { NodeSet set; for (unsigned i = 0; i < NodeSet::NUM_CORNER_BITS; ++i) { CPPUNIT_ASSERT( !set.corner_node(i) ); set.set_corner_node( i ); CPPUNIT_ASSERT( set.corner_node(i) ); set.clear_corner_node( i ); CPPUNIT_ASSERT( !set.corner_node(i) ); } for (unsigned i = 0; i < NodeSet::NUM_EDGE_BITS; ++i) { CPPUNIT_ASSERT( !set.mid_edge_node(i) ); set.set_mid_edge_node( i ); CPPUNIT_ASSERT( set.mid_edge_node(i) ); set.clear_mid_edge_node( i ); CPPUNIT_ASSERT( !set.mid_edge_node(i) ); } for (unsigned i = 0; i < NodeSet::NUM_FACE_BITS; ++i) { CPPUNIT_ASSERT( !set.mid_face_node(i) ); set.set_mid_face_node( i ); CPPUNIT_ASSERT( set.mid_face_node(i) ); set.clear_mid_face_node( i ); CPPUNIT_ASSERT( !set.mid_face_node(i) ); } for (unsigned i = 0; i < NodeSet::NUM_REGION_BITS; ++i) { CPPUNIT_ASSERT( !set.mid_region_node(i) ); set.set_mid_region_node( i ); CPPUNIT_ASSERT( set.mid_region_node(i) ); set.clear_mid_region_node( i ); CPPUNIT_ASSERT( !set.mid_region_node(i) ); } }
void QuadLagrangeShape::coefficients( Sample loc, NodeSet nodeset, double* coeff_out, size_t* indices_out, size_t& num_coeff, MsqError& err ) const { switch (loc.dimension) { case 0: num_coeff = 1; indices_out[0] = loc.number; coeff_out[0] = 1.0; break; case 1: coeff_out[0] = coeff_out[1] = coeff_out[2] = coeff_out[3] = coeff_out[4] = coeff_out[5] = coeff_out[6] = coeff_out[7] = coeff_out[8] = 0.0; if (nodeset.mid_edge_node(loc.number)) { // if mid-edge node is present num_coeff = 1; indices_out[0] = loc.number+4; coeff_out[0] = 1.0; } else { // If mid-edge node is not present, mapping function value // for linear edge is even weight of adjacent vertices. num_coeff = 2; indices_out[0] = loc.number; indices_out[1] = (loc.number+1)%4; coeff_out[0] = 0.5; coeff_out[1] = 0.5; } break; case 2: if (nodeset.mid_face_node(0)) { // if quad center node is present num_coeff = 1; indices_out[0] = 8; coeff_out[0] = 1.0; } else { // for linear element, (no mid-edge nodes), all corners contribute 1/4. num_coeff = 4; indices_out[0] = 0; indices_out[1] = 1; indices_out[2] = 2; indices_out[3] = 3; coeff_out[0] = 0.25; coeff_out[1] = 0.25; coeff_out[2] = 0.25; coeff_out[3] = 0.25; // add in contribution for any mid-edge nodes present for (int i = 0; i < 4; ++i) { // for each edge if (nodeset.mid_edge_node(i)) { indices_out[num_coeff] = i+4; coeff_out[num_coeff] = 0.5; coeff_out[ i ] -= 0.25; coeff_out[(i+1)%4] -= 0.25; ++num_coeff; } } } break; default: MSQ_SETERR(err)(MsqError::UNSUPPORTED_ELEMENT, "Request for dimension %d mapping function value" "for a quadrilateral element", loc.dimension); } }
static void derivatives_at_mid_edge( unsigned edge, NodeSet nodeset, size_t* vertices, MsqVector<2>* derivs, size_t& num_vtx ) { static const double values[][9] = { {-0.5, -0.5, 0.5, 0.5, -1.0, 2.0, 1.0, 2.0, 4.0}, {-0.5, 0.5, 0.5, -0.5, -2.0, 1.0, -2.0, -1.0, -4.0}, {-0.5, -0.5, 0.5, 0.5, -1.0, -2.0, 1.0, -2.0, -4.0}, {-0.5, 0.5, 0.5, -0.5, 2.0, 1.0, 2.0, -1.0, 4.0} }; static const double edge_values[][2] = { {-1, 1}, {-1, 1}, { 1, -1}, { 1, -1} }; const unsigned prev_corner = edge; // index of start vertex of edge const unsigned next_corner = (edge+1)%4; // index of end vertex of edge const unsigned is_eta_edge = edge % 2; // edge is xi = +/- 0 const unsigned is_xi_edge = 1 - is_eta_edge;// edge is eta = +/- 0 //const unsigned mid_edge_node = edge + 4; // mid-edge node index const unsigned prev_opposite = (prev_corner+3)%4; // index of corner adjacent to prev_corner const unsigned next_opposite = (next_corner+1)%4; // index of corner adjacent to next_corner; // First do derivatives along edge (e.g. wrt xi if edge is eta = +/-1) num_vtx = 2; vertices[0] = prev_corner; vertices[1] = next_corner; derivs[0][is_eta_edge] = edge_values[edge][0]; derivs[0][is_xi_edge] = 0.0; derivs[1][is_eta_edge] = edge_values[edge][1]; derivs[1][is_xi_edge] = 0.0; // That's it for the edge-direction derivatives. No other vertices contribute. // Next handle the linear element case. Handle this as a special case first, // so the generalized solution doesn't impact performance for linear elements // too much. if (!nodeset.have_any_mid_node()) { num_vtx = 4; vertices[2] = prev_opposite; vertices[3] = next_opposite; derivs[0][is_xi_edge] = values[edge][prev_corner]; derivs[1][is_xi_edge] = values[edge][next_corner]; derivs[2][is_xi_edge] = values[edge][prev_opposite]; derivs[2][is_eta_edge] = 0.0; derivs[3][is_xi_edge] = values[edge][next_opposite]; derivs[3][is_eta_edge] = 0.0; return; } // Initial (linear) contribution for each corner double v[4] = { values[edge][0], values[edge][1], values[edge][2], values[edge][3] }; // If mid-face node is present double v8 = 0.0; if (nodeset.mid_face_node(0)) { v8 = values[edge][8]; vertices[num_vtx] = 8; derivs[num_vtx][is_eta_edge] = 0.0; derivs[num_vtx][is_xi_edge] = v8; v[0] -= 0.25 * v8; v[1] -= 0.25 * v8; v[2] -= 0.25 * v8; v[3] -= 0.25 * v8; ++num_vtx; } // If mid-edge nodes are present for (unsigned i = 0; i < 4; ++i) { if (nodeset.mid_edge_node(i)) { const double value = values[edge][i+4] - 0.5 * v8; if (fabs(value) > 0.125) { v[ i ] -= 0.5 * value; v[(i+1)%4] -= 0.5 * value; vertices[num_vtx] = i+4; derivs[num_vtx][is_eta_edge] = 0.0; derivs[num_vtx][is_xi_edge] = value; ++num_vtx; } } } // update values for adjacent corners derivs[0][is_xi_edge] = v[prev_corner]; derivs[1][is_xi_edge] = v[next_corner]; // do other two corners if (fabs(v[prev_opposite]) > 0.125) { vertices[num_vtx] = prev_opposite; derivs[num_vtx][is_eta_edge] = 0.0; derivs[num_vtx][is_xi_edge] = v[prev_opposite]; ++num_vtx; } if (fabs(v[next_opposite]) > 0.125) { vertices[num_vtx] = next_opposite; derivs[num_vtx][is_eta_edge] = 0.0; derivs[num_vtx][is_xi_edge] = v[next_opposite]; ++num_vtx; } }