예제 #1
0
void NodeSetTest::test_have_any()
{
  NodeSet set;
  set.clear();
  
  CPPUNIT_ASSERT( !set.have_any_corner_node() );
  set.set_corner_node(0);
  CPPUNIT_ASSERT( set.have_any_corner_node() );
  set.clear_corner_node(0);
  CPPUNIT_ASSERT( !set.have_any_corner_node() );
  set.set_corner_node( NodeSet::NUM_CORNER_BITS-1 );
  CPPUNIT_ASSERT( set.have_any_corner_node() );
  CPPUNIT_ASSERT( !set.have_any_mid_node() );

  CPPUNIT_ASSERT( !set.have_any_mid_edge_node() );
  set.set_mid_edge_node(0);
  CPPUNIT_ASSERT( set.have_any_mid_edge_node() );
  CPPUNIT_ASSERT( set.have_any_mid_node() );
  set.clear_mid_edge_node(0);
  CPPUNIT_ASSERT( !set.have_any_mid_edge_node() );
  CPPUNIT_ASSERT( !set.have_any_mid_node() );
  set.set_mid_edge_node( NodeSet::NUM_EDGE_BITS-1 );
  CPPUNIT_ASSERT( set.have_any_mid_edge_node() );
  CPPUNIT_ASSERT( set.have_any_mid_node() );
  set.clear();

  CPPUNIT_ASSERT( !set.have_any_mid_face_node() );
  set.set_mid_face_node(0);
  CPPUNIT_ASSERT( set.have_any_mid_face_node() );
  CPPUNIT_ASSERT( set.have_any_mid_node() );
  set.clear_mid_face_node(0);
  CPPUNIT_ASSERT( !set.have_any_mid_face_node() );
  CPPUNIT_ASSERT( !set.have_any_mid_node() );
  set.set_mid_face_node( NodeSet::NUM_FACE_BITS-1 );
  CPPUNIT_ASSERT( set.have_any_mid_face_node() );
  CPPUNIT_ASSERT( set.have_any_mid_node() );
  set.clear();

  CPPUNIT_ASSERT( !set.have_any_mid_region_node() );
  set.set_mid_region_node(0);
  CPPUNIT_ASSERT( set.have_any_mid_region_node() );
  CPPUNIT_ASSERT( set.have_any_mid_node() );
  set.clear_mid_region_node(0);
  CPPUNIT_ASSERT( !set.have_any_mid_region_node() );
  CPPUNIT_ASSERT( !set.have_any_mid_node() );
  set.set_mid_region_node( NodeSet::NUM_REGION_BITS-1 );
  CPPUNIT_ASSERT( set.have_any_mid_region_node() );
  CPPUNIT_ASSERT( set.have_any_mid_node() );
  set.clear();
}
예제 #2
0
void TriLagrangeShape::derivatives( Sample loc,
                                    NodeSet nodeset,
                                    size_t* vertex_indices_out,
                                    MsqVector<2>* d_coeff_d_xi_out,
                                    size_t& num_vtx,
                                    MsqError& err ) const
{
  if (!nodeset.have_any_mid_node()) {
    num_vtx = 3;
    get_linear_derivatives( vertex_indices_out, d_coeff_d_xi_out );
    return;
  }

  if (nodeset.have_any_mid_face_node()) {
    MSQ_SETERR(err)("TriLagrangeShape does not support mid-element nodes",
                    MsqError::UNSUPPORTED_ELEMENT);
    return;
  }
  
  switch (loc.dimension) {
    case 0:
      derivatives_at_corner( loc.number, nodeset, vertex_indices_out, d_coeff_d_xi_out, num_vtx );
      break;
    case 1:
      derivatives_at_mid_edge( loc.number, nodeset, vertex_indices_out, d_coeff_d_xi_out, num_vtx );
      break;
    case 2:
      derivatives_at_mid_elem( nodeset, vertex_indices_out, d_coeff_d_xi_out, num_vtx );
      break;
    default:
      MSQ_SETERR(err)("Invalid/unsupported logical dimension",MsqError::INVALID_ARG);
  }
}
예제 #3
0
void LinearPyramid::coefficients( Sample loc,
                                  NodeSet nodeset,
                                  double* coeff_out,
                                  size_t* indices_out,
                                  size_t& num_coeff,
                                  MsqError& err ) const
{
  if (nodeset.have_any_mid_node()) {
    MSQ_SETERR(err)(nonlinear_error, MsqError::UNSUPPORTED_ELEMENT );
    return;
  }
  
  switch (loc.dimension) {
    case 0:
      coefficients_at_corner( loc.number, coeff_out, indices_out, num_coeff );
      break;
    case 1:
      coefficients_at_mid_edge( loc.number, coeff_out, indices_out, num_coeff );
      break;
    case 2:
      coefficients_at_mid_face( loc.number, coeff_out, indices_out, num_coeff );
      break;
    case 3:
      coefficients_at_mid_elem( coeff_out, indices_out, num_coeff );
      break;
    default:
      MSQ_SETERR(err)("Invalid/unsupported logical dimension",MsqError::INVALID_ARG);
  }
}
예제 #4
0
void LinearHexahedron::derivatives( Sample loc,
                                    NodeSet nodeset,
                                    size_t* vertex_indices_out,
                                    MsqVector<3>* d_coeff_d_xi_out,
                                    size_t& num_vtx,
                                    MsqError& err ) const
{
  if (nodeset.have_any_mid_node()) {
    MSQ_SETERR(err)(nonlinear_error, MsqError::UNSUPPORTED_ELEMENT );
    return;
  }
  
  switch (loc.dimension) {
    case 0:
      derivatives_at_corner( loc.number, vertex_indices_out, d_coeff_d_xi_out, num_vtx );
      break;
    case 1:
      derivatives_at_mid_edge( loc.number, vertex_indices_out, d_coeff_d_xi_out, num_vtx );
      break;
    case 2:
      derivatives_at_mid_face( loc.number, vertex_indices_out, d_coeff_d_xi_out, num_vtx );
      break;
    case 3:
      derivatives_at_mid_elem( vertex_indices_out, d_coeff_d_xi_out, num_vtx );
      break;
    default:
      MSQ_SETERR(err)("Invalid/unsupported logical dimension",MsqError::INVALID_ARG);
  }
}
void LinearTetrahedron::derivatives( Sample ,
                                     NodeSet nodeset,
                                     size_t* vertices,
                                     MsqVector<3>* coeff_derivs,
                                     size_t& num_vtx,
                                     MsqError& err ) const
{
  if (nodeset.have_any_mid_node()) {
    MSQ_SETERR(err)(nonlinear_error, MsqError::UNSUPPORTED_ELEMENT );
    return;
  }
  else {
    num_vtx = 4;
    vertices[0] = 0;
    vertices[1] = 1;
    vertices[2] = 2;
    vertices[3] = 3;
    
    coeff_derivs[0][0] = -1.0;
    coeff_derivs[0][1] = -1.0;
    coeff_derivs[0][2] = -1.0;

    coeff_derivs[1][0] =  1.0;
    coeff_derivs[1][1] =  0.0;
    coeff_derivs[1][2] =  0.0;

    coeff_derivs[2][0] =  0.0;
    coeff_derivs[2][1] =  1.0;
    coeff_derivs[2][2] =  0.0;

    coeff_derivs[3][0] =  0.0;
    coeff_derivs[3][1] =  0.0;
    coeff_derivs[3][2] =  1.0;
  }
}
예제 #6
0
NodeSet TriLagrangeShape::sample_points( NodeSet ns ) const
{
  if (ns.have_any_mid_node()) {
    ns.set_all_corner_nodes(TRIANGLE);
  }
  else {
    ns.clear();
    ns.set_mid_face_node(0);
  }
  return ns;
}
void LinearTetrahedron::coefficients( Sample location,
                                      NodeSet nodeset,
                                      double* coeff_out,
                                      size_t* indices_out,
                                      size_t& num_coeff,
                                      MsqError& err ) const
{
  if (nodeset.have_any_mid_node()) {
    MSQ_SETERR(err)(nonlinear_error, MsqError::UNSUPPORTED_ELEMENT );
    return;
  }
  
  switch (location.dimension) {
    case 0:
      num_coeff = 1;
      indices_out[0] = location.number;
      coeff_out[0] = 1.0;
      break;
    case 1:
      num_coeff = 2;
      coeff_out[0] = 0.5;
      coeff_out[1] = 0.5;
      if (location.number < 3) {
        indices_out[0] = location.number;
        indices_out[1] = (location.number+1)%3;
      }
      else {
        indices_out[0] = location.number - 3;
        indices_out[1] = 3;
      }
      break;
    case 2:
      num_coeff = 3;
      indices_out[0] = faces[location.number][0];
      indices_out[1] = faces[location.number][1];
      indices_out[2] = faces[location.number][2];
      coeff_out[0] = coeff_out[1] = coeff_out[2] = coeff_out[3] = MSQ_ONE_THIRD;
      break;
    case 3:
      num_coeff = 4;
      indices_out[0] = 0;
      indices_out[1] = 1;
      indices_out[2] = 2;
      indices_out[3] = 3;
      coeff_out[0] = coeff_out[1] = coeff_out[2] = coeff_out[3] = 0.25;
      break;
    default:
      MSQ_SETERR(err)("Invalid/unsupported logical dimension",MsqError::INVALID_ARG);
  }
}
예제 #8
0
void LinearPyramid::derivatives( Sample loc,
                                 NodeSet nodeset,
                                 size_t* vertex_indices_out,
                                 MsqVector<3>* d_coeff_d_xi_out,
                                 size_t& num_vtx,
                                 MsqError& err ) const
{
  if (nodeset.have_any_mid_node()) {
    MSQ_SETERR(err)(nonlinear_error, MsqError::UNSUPPORTED_ELEMENT );
    return;
  }
  
  switch (loc.dimension) {
    case 0:
      if (loc.number == 4) {
        set_equal_derivatives( 0.0, vertex_indices_out, d_coeff_d_xi_out, num_vtx );
      }
      else {
        set_corner_derivatives( loc.number, 1.0, vertex_indices_out, d_coeff_d_xi_out, num_vtx );
      }
      break;
    case 1:
      if (loc.number < 4) {
        set_edge_derivatives( loc.number, 0.50, vertex_indices_out, d_coeff_d_xi_out, num_vtx );
      }
      else {
        set_corner_derivatives( loc.number-4, 0.50, vertex_indices_out, d_coeff_d_xi_out, num_vtx );
      }    
      break;
    case 2:
      if (loc.number == 4) {
        set_equal_derivatives( 0.5, vertex_indices_out, d_coeff_d_xi_out, num_vtx );
      }
      else {
        set_edge_derivatives( loc.number, 0.25, vertex_indices_out, d_coeff_d_xi_out, num_vtx );
      }
      break;
    case 3:
      set_equal_derivatives( 0.25, vertex_indices_out, d_coeff_d_xi_out, num_vtx );
      break;
    default:
      MSQ_SETERR(err)("Invalid/unsupported logical dimension",MsqError::INVALID_ARG);
  }
}
예제 #9
0
static void derivatives_at_mid_elem( NodeSet nodeset,
                                     size_t* vertices,
                                     MsqVector<2>* derivs,
                                     size_t& num_vtx )
{
    // fast linear case
    // This is provided as an optimization for linear elements.
    // If this block of code were removed, the general-case code
    // below should produce the same result.
  if (!nodeset.have_any_mid_node()) {
    num_vtx = 4;
    vertices[0] = 0; derivs[0][0] = -0.5; derivs[0][1] = -0.5;
    vertices[1] = 1; derivs[1][0] =  0.5; derivs[1][1] = -0.5;
    vertices[2] = 2; derivs[2][0] =  0.5; derivs[2][1] =  0.5;
    vertices[3] = 3; derivs[3][0] = -0.5; derivs[3][1] =  0.5;
    return;
  }
  
  num_vtx = 0;
  
    // N_0
  if (!nodeset.both_edge_nodes(0,3)) {  // if eiter adjacent mid-edge node is missing
    vertices[num_vtx] = 0;
    derivs[num_vtx][0] = nodeset.mid_edge_node(3) ? 0.0 : -0.5;
    derivs[num_vtx][1] = nodeset.mid_edge_node(0) ? 0.0 : -0.5;
    ++num_vtx;
  }
  
    // N_1
  if (!nodeset.both_edge_nodes(0,1)) {  // if eiter adjacent mid-edge node is missing
    vertices[num_vtx] = 1;
    derivs[num_vtx][0] = nodeset.mid_edge_node(1) ? 0.0 :  0.5;
    derivs[num_vtx][1] = nodeset.mid_edge_node(0) ? 0.0 : -0.5;
    ++num_vtx;
  }
  
    // N_2
  if (!nodeset.both_edge_nodes(1,2)) {  // if eiter adjacent mid-edge node is missing
    vertices[num_vtx] = 2;
    derivs[num_vtx][0] = nodeset.mid_edge_node(1) ? 0.0 :  0.5;
    derivs[num_vtx][1] = nodeset.mid_edge_node(2) ? 0.0 :  0.5;
    ++num_vtx;
  }
  
    // N_3
  if (!nodeset.both_edge_nodes(2,3)) {  // if eiter adjacent mid-edge node is missing
    vertices[num_vtx] = 3;
    derivs[num_vtx][0] = nodeset.mid_edge_node(3) ? 0.0 : -0.5;
    derivs[num_vtx][1] = nodeset.mid_edge_node(2) ? 0.0 :  0.5;
    ++num_vtx;
  }
  
    // N_4
  if (nodeset.mid_edge_node(0)) {
    vertices[num_vtx] = 4;
    derivs[num_vtx][0] =  0.0;
    derivs[num_vtx][1] = -1.0;
    ++num_vtx;
  }
  
    // N_5
  if (nodeset.mid_edge_node(1)) {
    vertices[num_vtx] = 5;
    derivs[num_vtx][0] =  1.0;
    derivs[num_vtx][1] =  0.0;
    ++num_vtx;
  }
  
    // N_6
  if (nodeset.mid_edge_node(2)) {
    vertices[num_vtx] = 6;
    derivs[num_vtx][0] =  0.0;
    derivs[num_vtx][1] =  1.0;
    ++num_vtx;
  }
  
    // N_7
  if (nodeset.mid_edge_node(3)) {
    vertices[num_vtx] = 7;
    derivs[num_vtx][0] = -1.0;
    derivs[num_vtx][1] =  0.0;
    ++num_vtx;
  }
  
    // N_8 (mid-quad node) never contributes to Jacobian at element center!!!
}
예제 #10
0
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;
  }
}