double snlCtrlPointNetSurface::calcFlatness ( int indexU, int indexV, int numPointsU, int numPointsV )
{
    // Calculate flatness of a rectangular section of control points.
    // --------------------------------------------------------------
    // indexU:      U index of starting position in control point net.
    // indexV:      V index of starting position in control point net.
    // numPointsU:  Number of points in U direction, including starting point, to test.
    // numPointsV:  Number of points in V direction, including starting point, to test.
    //
    // Notes:
    //
    //              Rectangle data orientation:
    //
    //                V     B--------D
    //                      |        |
    //                ^     |        |
    //                |     |        |
    //                |     A--------C
    //
    //                      ----->   U

    // Locate rectangular array of points to process.

    int numPoints = numPointsU * numPointsV;

    snlCtrlPoint** ctrlPointPtrs = new snlCtrlPoint* [ numPoints ];

    locatePoints ( indexU, indexV, numPointsU, numPointsV, ctrlPointPtrs );

    // Pre-calculate vectors and normals.

    // 4 Corners.
    
    int indexB = numPointsV - 1;
    int indexC = numPoints - numPointsV;
    int indexD = numPoints - 1;

    snlCtrlPoint ptA = *(ctrlPointPtrs [ 0 ]);
    ptA.normalise();
    snlCtrlPoint ptB = *(ctrlPointPtrs [ numPointsV - 1 ]);
    ptB.normalise();
    snlCtrlPoint ptC = *(ctrlPointPtrs [ numPoints - numPointsV ]);
    ptC.normalise();
    snlCtrlPoint ptD = *(ctrlPointPtrs [ numPoints - 1 ]);
    ptD.normalise();

    // Side Vectors.
    
    snlVector ab ( ptA, ptB );
    ab.unitise();
    
    snlVector ba = ab * -1.0;

    snlVector ac ( ptA, ptC );
    ac.unitise();

    snlVector ca = ac * -1.0;

    snlVector bd ( ptB, ptD );
    bd.unitise();

    snlVector db = bd * -1.0;

    snlVector cd ( ptC, ptD );
    cd.unitise();

    snlVector dc = cd * -1.0;

    // Diagonal Vectors.

    snlVector bc ( ptB, ptC );
    snlVector ad ( ptA, ptD );

    // Normals.

    snlVector normA ( ac, ab );
    snlVector normB ( ba, bd );
    snlVector normC ( cd, ca );
    snlVector normD ( db, dc );

    // Project each point of the rectangle, not on the corners, onto the 4 base triangles.
    // If the projection does not lay on a triangle, it is not considered in any further flatness
    // calculations. If a point does not have any projections that lay on one of the four triangles
    // then the closest distance to one of the 6 vectors defining the 4 triangles is taken
    // as the flatness.

    double maxDistance = 0.0;  // Maximum distance or "flatness".

    for ( int index = 0; index < indexD; index ++ )
    {
        if ( ! index || index == indexB || index == indexC ) continue;  // Don't process the corners.

        bool interiorFound = false;  // True if at least one triangle contains projection.

        snlCtrlPoint t = *(ctrlPointPtrs [ index ]);
        t.normalise();

        // Project point to and compare to triangle rooted at A.

        snlVector toProj ( ptA, t );

        snlVector projVect = toProj.project ( normA );

        snlPoint projPoint = t - projVect;

        double projDist = projVect.length();

        bool isInterior = isInteriorToTriangle ( projPoint, ptA, ab, ac, ptB, ba, bc );

        if ( isInterior ) interiorFound = true;

        if ( isInterior &&  maxDistance < projDist ) maxDistance = projDist;

        // Project point to and compare to triangle rooted at B.

        toProj.calc ( ptB, t );

        projVect = toProj.project ( normB );

        projPoint = t - projVect;

        projDist = projVect.length();

        isInterior = isInteriorToTriangle ( projPoint, ptB, ba, bd, ptA, ab, ad );

        if ( isInterior ) interiorFound = true;

        if ( isInterior &&  maxDistance < projDist ) maxDistance = projDist;
        
        // Project point to and compare to triangle rooted at C.

        toProj.calc ( ptC, t );

        projVect = toProj.project ( normC );

        projPoint = t - projVect;

        projDist = projVect.length();

        isInterior = isInteriorToTriangle ( projPoint, ptC, ca, cd, ptA, ac, ad );

        if ( isInterior ) interiorFound = true;

        if ( isInterior &&  maxDistance < projDist ) maxDistance = projDist;
        
        // Project point to and compare to triangle rooted at D.

        toProj.calc ( ptD, t );

        projVect = toProj.project ( normD );

        projPoint = t - projVect;

        projDist = projVect.length();

        isInterior = isInteriorToTriangle ( projPoint, ptD, db, dc, ptB, bd, bc );

        if ( isInterior ) interiorFound = true;

        if ( isInterior &&  maxDistance < projDist ) maxDistance = projDist;
        
        // If no triangle contains a projection then project to the six triangle outlines and take _smallest_ value

        if ( ! interiorFound )
        {
            toProj.calc ( ptA, t );

            double projMaxDistance = ab.projectDist ( toProj );  // A -> B.

            double projDist = ac.projectDist ( toProj );  // A -> C.

            if ( projDist < projMaxDistance ) projMaxDistance = projDist;

            projDist = ad.projectDist ( toProj );  // A -> D.

            if ( projDist < projMaxDistance ) projMaxDistance = projDist;

            toProj.calc ( ptD, t );

            projDist = db.projectDist ( toProj );  // D -> B.

            if ( projDist < projMaxDistance ) projMaxDistance = projDist;

            projDist = dc.projectDist ( toProj );  // D -> C.

            if ( projDist < projMaxDistance ) projMaxDistance = projDist;

            toProj.calc ( ptB, t );

            projDist = bc.projectDist ( toProj );  // B -> C.

            if ( projDist < projMaxDistance ) projMaxDistance = projDist;

            if ( maxDistance < projMaxDistance ) maxDistance = projMaxDistance;
        }
    }

    return maxDistance;
}
Exemplo n.º 2
0
int main(int argc, char *argv[]) {
    
#ifdef HAVE_MPI
  // Initialize MPI and setup an Epetra communicator
  MPI_Init(&argc,&argv);
  Epetra_MpiComm Comm(MPI_COMM_WORLD);
#else
  // If we aren't using MPI, then setup a serial communicator.
  Epetra_SerialComm Comm;
#endif

  // Some typedefs for oft-used data types
  typedef Epetra_MultiVector MV;
  typedef Epetra_Operator OP;
  typedef Belos::MultiVecTraits<double, Epetra_MultiVector> MVT;

  bool ierr;

  // Get our processor ID (0 if running serial)
  int MyPID = Comm.MyPID();

  // Verbose flag: only processor 0 should print
  bool verbose = (MyPID==0);

  // Initialize a Gallery object, from which we will select a matrix
  // Select a 2-D laplacian, of order 100
  Trilinos_Util::CrsMatrixGallery Gallery("laplace_2d", Comm);
  Gallery.Set("problem_size", 100);

  // Say hello and print some information about the gallery matrix
  if (verbose) {
    cout << "Belos Example: Block CG" << endl;
    cout << "Problem info:" << endl;
    cout << Gallery;
    cout << endl;
  }

  // Setup some more problem/solver parameters:

  // Block size
  int blocksize = 4;

  // Get a pointer to the system matrix, inside of a Teuchos::RCP
  // The Teuchos::RCP is a reference counting pointer that handles
  // garbage collection for us, so that we can perform memory allocation without
  // having to worry about freeing memory manually.
  Teuchos::RCP<Epetra_CrsMatrix> A = Teuchos::rcp( Gallery.GetMatrix(), false );

  // Create an Belos MultiVector, based on Epetra MultiVector
  const Epetra_Map * Map = &(A->RowMap());
  Teuchos::RCP<Epetra_MultiVector> B = 
    Teuchos::rcp( new Epetra_MultiVector(*Map,blocksize) );
  Teuchos::RCP<Epetra_MultiVector> X = 
    Teuchos::rcp( new Epetra_MultiVector(*Map,blocksize) );

  // Initialize the solution with zero and right-hand side with random entries
  X->PutScalar( 0.0 );
  B->Random();

  // Setup the linear problem, with the matrix A and the vectors X and B
  Teuchos::RCP< Belos::LinearProblem<double,MV,OP> > myProblem = 
    Teuchos::rcp( new Belos::LinearProblem<double,MV,OP>(A, X, B) );

  // The 2-D laplacian is symmetric. Specify this in the linear problem.
  myProblem->setHermitian();

  // Signal that we are done setting up the linear problem
  ierr = myProblem->setProblem();

  // Check the return from setProblem(). If this is true, there was an
  // error. This probably means we did not specify enough information for
  // the eigenproblem.
  assert(ierr == true);

  // Specify the verbosity level. Options include:
  // Belos::Errors 
  //   This option is always set
  // Belos::Warnings 
  //   Warnings (less severe than errors)
  // Belos::IterationDetails 
  //   Details at each iteration, such as the current eigenvalues
  // Belos::OrthoDetails 
  //   Details about orthogonality
  // Belos::TimingDetails
  //   A summary of the timing info for the solve() routine
  // Belos::FinalSummary 
  //   A final summary 
  // Belos::Debug 
  //   Debugging information
  int verbosity = Belos::Warnings + Belos::Errors + Belos::FinalSummary + Belos::TimingDetails;

  // Create the parameter list for the eigensolver
  Teuchos::RCP<Teuchos::ParameterList> myPL = Teuchos::rcp( new Teuchos::ParameterList() );
  myPL->set( "Verbosity", verbosity );
  myPL->set( "Block Size", blocksize );
  myPL->set( "Maximum Iterations", 100 );
  myPL->set( "Convergence Tolerance", 1.0e-8 );

  // Create the Block CG solver
  // This takes as inputs the linear problem and the solver parameters
  Belos::BlockCGSolMgr<double,MV,OP> mySolver(myProblem, myPL);

  // Solve the linear problem, and save the return code
  Belos::ReturnType solverRet = mySolver.solve();

  // Check return code of the solver: Unconverged, Failed, or OK
  switch (solverRet) {

  // UNCONVERGED
  case Belos::Unconverged:
    if (verbose) 
      cout << "Belos::BlockCGSolMgr::solve() did not converge!" << endl;
#ifdef HAVE_MPI
    MPI_Finalize();
#endif
    return 0;
    break;

  // CONVERGED
  case Belos::Converged:
    if (verbose) 
      cout << "Belos::BlockCGSolMgr::solve() converged!" << endl;
    break;
  }

  // Test residuals
  Epetra_MultiVector R( B->Map(), blocksize );

  // R = A*X
  A->Apply( *X, R );

  // R -= B 
  MVT::MvAddMv( -1.0, *B, 1.0, R, R );

  // Compute the 2-norm of each vector in the MultiVector
  // and store them to a std::vector<double>
  std::vector<double> normR(blocksize), normB(blocksize);
  MVT::MvNorm( R, normR );
  MVT::MvNorm( *B, normB );

  // Output results to screen
  if(verbose) {
    cout << scientific << setprecision(6) << showpoint;
    cout << "******************************************************\n"
         << "           Results (outside of linear solver)           \n" 
         << "------------------------------------------------------\n"
         << "  Linear System\t\tRelative Residual\n"
         << "------------------------------------------------------\n";
    for( int i=0 ; i<blocksize ; ++i ) {
      cout << "  " << i+1 << "\t\t\t" << normR[i]/normB[i] << endl;
    }
    cout << "******************************************************\n" << endl;
  }


#ifdef HAVE_MPI
  MPI_Finalize();
#endif

  return(EXIT_SUCCESS);
}