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; }
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); }