/* Do transform M_hat = S_a M_{3x2}, M_{2x2} Theta^-1 M_hat
 * where the plane into which we are projecting is orthogonal
 * to the passed u vector.
 */
static inline bool
project_to_perp_plane(  MsqMatrix<3,2> J,
                        const MsqVector<3>& u,
                        const MsqVector<3>& u_perp,
                        MsqMatrix<2,2>& A,
                        MsqMatrix<3,2>& S_a_transpose_Theta )
{
    MsqVector<3> n_a = J.column(0) * J.column(1);
    double sc, len = length(n_a);
    if (!divide(1.0, len, sc))
        return false;
    n_a *= sc;
    double ndot = n_a % u;
    double sigma = (ndot < 0.0) ? -1 : 1;
    double cosphi = sigma * ndot;
    MsqVector<3> cross = n_a * u;
    double sinphi = length(cross);

    MsqMatrix<3,2> Theta;
    Theta.set_column(0,   u_perp);
    Theta.set_column(1, u*u_perp);

    // If columns of J are not in plane orthogonal to u, then
    // rotate J such that they are.
    if (sinphi > 1e-12) {
        MsqVector<3> m = sigma * cross;
        MsqVector<3> n = (1/sinphi) * m;
        MsqVector<3> p = (1-cosphi) * n;
        double s_a[] =
        {   p[0]*n[0] + cosphi, p[0]*n[1] - m[2],   p[0]*n[2] + m[1],
            p[1]*n[0] + m[2],   p[1]*n[1] + cosphi, p[1]*n[2] - m[0],
            p[2]*n[0] - m[1],   p[2]*n[1] + m[0],   p[2]*n[2] + cosphi
        };
        MsqMatrix<3,3> S_a(s_a);
        J = S_a * J;
        S_a_transpose_Theta = transpose(S_a) * Theta;
    }
    else {
        S_a_transpose_Theta = Theta;
//    J *= sigma;
    }

    // Project to get 2x2 A from A_hat (which might be equal to J)
    A = transpose(Theta) * J;
    return true;
}
Beispiel #2
0
template <class QMType> inline
void TMPQualityMetricTest<QMType>::test_evaluate_3D()
{
  MsqPrintError err(cout);
  PatchData pd;
  bool rval;
  double value;
  
  QMType m( &ideal, &faux_two );
  
    // test with aligned elements
  faux_two.count = 0;
  tester.get_ideal_element( HEXAHEDRON, true, pd );
  rval = m.evaluate( pd, 0, value, err );
  CPPUNIT_ASSERT(!MSQ_CHKERR(err));
  CPPUNIT_ASSERT(rval);
  CPPUNIT_ASSERT_DOUBLES_EQUAL( faux_two.value, value, DBL_EPSILON );
  CPPUNIT_ASSERT_EQUAL( 1, faux_two.count );
  
    // test that columns are orthogonal for ideal hex element
  MsqMatrix<3,3> A = faux_two.last_A_3D;
  CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, A.column(0) % A.column(1), 1e-6 );
  CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, A.column(0) % A.column(2), 1e-6 );
  CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, A.column(1) % A.column(2), 1e-6 );
  
    // test with rotated element
  faux_two.count = 0;
  tester.get_ideal_element( TETRAHEDRON, true, pd );
  // rotate by 90-degrees about X axis
  for (size_t i = 0; i < pd.num_nodes(); ++i) {
    Vector3D orig = pd.vertex_by_index(i);
    Vector3D newp( orig[0], -orig[2], orig[1] );
    pd.set_vertex_coordinates( newp, i, err );
  }
  rval = m.evaluate( pd, 0, value, err );
  CPPUNIT_ASSERT(!MSQ_CHKERR(err));
  CPPUNIT_ASSERT(rval);
  CPPUNIT_ASSERT_DOUBLES_EQUAL( faux_two.value, value, DBL_EPSILON );
  CPPUNIT_ASSERT_EQUAL( 1, faux_two.count );
}
Beispiel #3
0
  void test_3d_eval_ortho_hex()
    {
      MsqPrintError err(cout);
      PatchData pd;
      bool rval;
      double value;

      QMType m( &ideal, &faux_zero );
      faux_zero.count = 0;

      tester.get_ideal_element( HEXAHEDRON, true, pd );
      rval = m.evaluate( pd, 0, value, err );
      CPPUNIT_ASSERT(!MSQ_CHKERR(err));
      CPPUNIT_ASSERT(rval);
      CPPUNIT_ASSERT_EQUAL( 1, faux_zero.count );

        // test that columns are orthogonal for ideal hex element
      MsqMatrix<3,3> A = faux_zero.last_A_3D;
      CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, A.column(0) % A.column(1), 1e-6 );
      CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, A.column(0) % A.column(2), 1e-6 );
      CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, A.column(1) % A.column(2), 1e-6 );
    }  
Beispiel #4
0
bool LambdaTarget::get_surface_target( PatchData& pd,
                                       size_t element,
                                       Sample sample,
                                       MsqMatrix<3,2>& W_out,
                                       MsqError& err )
{
    bool valid = lambdaSource->get_surface_target( pd, element, sample, W_out, err );
    if (MSQ_CHKERR(err) && !valid)
        return false;
    MsqVector<3> cross = W_out.column(0) * W_out.column(1);
    double det1 = cross % cross; // length squared

    valid = compositeSource->get_surface_target( pd, element, sample, W_out, err );
    if (MSQ_CHKERR(err) && !valid)
        return false;
    cross = W_out.column(0) * W_out.column(1);
    double det2 = cross % cross; // length squared

    if (det2 < 1e-15)
        return false;

    W_out *= sqrt( sqrt( det1/det2 ) );
    return true;
}