// ====================================================================== bool BasicTest(string PrecType, const Teuchos::RefCountPtr<Epetra_RowMatrix>& A,bool backward, bool reorder=false) { Epetra_MultiVector LHS(A->RowMatrixRowMap(), NumVectors); Epetra_MultiVector RHS(A->RowMatrixRowMap(), NumVectors); LHS.PutScalar(0.0); RHS.Random(); double starting_residual = Galeri::ComputeNorm(&*A, &LHS, &RHS); Epetra_LinearProblem Problem(&*A, &LHS, &RHS); // Set up the list Teuchos::ParameterList List; List.set("relaxation: damping factor", 1.0); List.set("relaxation: sweeps",2550); List.set("relaxation: type", PrecType); if(backward) List.set("relaxation: backward mode",backward); // Reordering if needed int NumRows=A->NumMyRows(); std::vector<int> RowList(NumRows); if(reorder) { for(int i=0; i<NumRows; i++) RowList[i]=i; List.set("relaxation: number of local smoothing indices",NumRows); List.set("relaxation: local smoothing indices",RowList.size()>0? &RowList[0] : (int*)0); } Ifpack_PointRelaxation Point(&*A); Point.SetParameters(List); Point.Compute(); // use the preconditioner as solver, with 1550 iterations Point.ApplyInverse(RHS,LHS); // compute the real residual double residual = Galeri::ComputeNorm(&*A, &LHS, &RHS); if (A->Comm().MyPID() == 0 && verbose) cout << "||A * x - b||_2 (scaled) = " << residual / starting_residual << endl; // Jacobi is very slow to converge here if (residual / starting_residual < 1e-2) { if (verbose) cout << "BasicTest Test passed" << endl; return(true); } else { if (verbose) cout << "BasicTest Test failed!" << endl; return(false); } }
bool Test(const Teuchos::RefCountPtr<Epetra_RowMatrix>& Matrix, Teuchos::ParameterList& List) { int NumVectors = 1; bool UseTranspose = false; Epetra_MultiVector LHS(Matrix->OperatorDomainMap(),NumVectors); Epetra_MultiVector RHS(Matrix->OperatorRangeMap(),NumVectors); Epetra_MultiVector LHSexact(Matrix->OperatorDomainMap(),NumVectors); LHS.PutScalar(0.0); LHSexact.Random(); Matrix->Multiply(UseTranspose,LHSexact,RHS); Epetra_LinearProblem Problem(&*Matrix,&LHS,&RHS); Teuchos::RefCountPtr<T> Prec; Prec = Teuchos::rcp( new T(&*Matrix) ); assert(Prec != Teuchos::null); IFPACK_CHK_ERR(Prec->SetParameters(List)); IFPACK_CHK_ERR(Prec->Initialize()); IFPACK_CHK_ERR(Prec->Compute()); // create the AztecOO solver AztecOO AztecOOSolver(Problem); // specify solver AztecOOSolver.SetAztecOption(AZ_solver,AZ_gmres); AztecOOSolver.SetAztecOption(AZ_output,32); AztecOOSolver.SetPrecOperator(&*Prec); // solver. The solver should converge in one iteration, // or maximum two (numerical errors) AztecOOSolver.Iterate(1550,1e-8); cout << *Prec; vector<double> Norm(NumVectors); LHS.Update(1.0,LHSexact,-1.0); LHS.Norm2(&Norm[0]); for (int i = 0 ; i < NumVectors ; ++i) { cout << "Norm[" << i << "] = " << Norm[i] << endl; if (Norm[i] > 1e-3) return(false); } return(true); }
// ====================================================================== int AllSingle(const Teuchos::RefCountPtr<Epetra_RowMatrix>& A, Teuchos::RCP<Epetra_MultiVector> coord) { Epetra_MultiVector LHS(A->RowMatrixRowMap(), NumVectors); Epetra_MultiVector RHS(A->RowMatrixRowMap(), NumVectors); LHS.PutScalar(0.0); RHS.Random(); Epetra_LinearProblem Problem(&*A, &LHS, &RHS); Teuchos::ParameterList List; List.set("relaxation: damping factor", 1.0); List.set("relaxation: type", "symmetric Gauss-Seidel"); List.set("relaxation: sweeps",1); List.set("partitioner: overlap",0); List.set("partitioner: type", "line"); List.set("partitioner: line detection threshold",1.0); List.set("partitioner: x-coordinates",&(*coord)[0][0]); List.set("partitioner: y-coordinates",&(*coord)[1][0]); List.set("partitioner: z-coordinates",(double*) 0); RHS.PutScalar(1.0); LHS.PutScalar(0.0); Ifpack_BlockRelaxation<Ifpack_SparseContainer<Ifpack_Amesos> > Prec(&*A); Prec.SetParameters(List); Prec.Compute(); // set AztecOO solver object AztecOO AztecOOSolver(Problem); AztecOOSolver.SetAztecOption(AZ_solver,Solver); if (verbose) AztecOOSolver.SetAztecOption(AZ_output,32); else AztecOOSolver.SetAztecOption(AZ_output,AZ_none); AztecOOSolver.SetPrecOperator(&Prec); AztecOOSolver.Iterate(2550,1e-5); printf(" AllSingle iters %d \n",AztecOOSolver.NumIters()); return(AztecOOSolver.NumIters()); }
QString CEdge::DisplayParse( StringToString* filter ) { QString parse = LHS() + "( "; if( m_Daughters.count() ) { CEdge* daughter; for( daughter = m_Daughters.first(); daughter; daughter = m_Daughters.next() ) { parse += daughter->DisplayParse( filter ); parse += " "; } } else { if( filter ) parse += Filter( filter, RHS() ); else parse += RHS(); parse += " "; } return parse + ")"; }
// ====================================================================== int CompareLineSmootherEntries(const Teuchos::RefCountPtr<Epetra_RowMatrix>& A) { Epetra_MultiVector LHS(A->RowMatrixRowMap(), NumVectors); Epetra_MultiVector RHS(A->RowMatrixRowMap(), NumVectors); LHS.PutScalar(0.0); RHS.Random(); Epetra_LinearProblem Problem(&*A, &LHS, &RHS); Teuchos::ParameterList List; List.set("relaxation: damping factor", 1.0); List.set("relaxation: type", "symmetric Gauss-Seidel"); List.set("relaxation: sweeps",1); List.set("partitioner: overlap",0); List.set("partitioner: type", "line"); List.set("partitioner: line mode","matrix entries"); List.set("partitioner: line detection threshold",10.0); RHS.PutScalar(1.0); LHS.PutScalar(0.0); Ifpack_BlockRelaxation<Ifpack_SparseContainer<Ifpack_Amesos> > Prec(&*A); Prec.SetParameters(List); Prec.Compute(); // set AztecOO solver object AztecOO AztecOOSolver(Problem); AztecOOSolver.SetAztecOption(AZ_solver,Solver); if (verbose) AztecOOSolver.SetAztecOption(AZ_output,32); else AztecOOSolver.SetAztecOption(AZ_output,AZ_none); AztecOOSolver.SetPrecOperator(&Prec); AztecOOSolver.Iterate(2550,1e-5); return(AztecOOSolver.NumIters()); }
// ====================================================================== int CompareBlockOverlap(const Teuchos::RefCountPtr<Epetra_RowMatrix>& A, int Overlap) { Epetra_MultiVector LHS(A->RowMatrixRowMap(), NumVectors); Epetra_MultiVector RHS(A->RowMatrixRowMap(), NumVectors); LHS.PutScalar(0.0); RHS.Random(); Epetra_LinearProblem Problem(&*A, &LHS, &RHS); Teuchos::ParameterList List; List.set("relaxation: damping factor", 1.0); List.set("relaxation: type", "Jacobi"); List.set("relaxation: sweeps",1); List.set("partitioner: overlap", Overlap); List.set("partitioner: type", "linear"); List.set("partitioner: local parts", 16); RHS.PutScalar(1.0); LHS.PutScalar(0.0); Ifpack_BlockRelaxation<Ifpack_SparseContainer<Ifpack_Amesos> > Prec(&*A); Prec.SetParameters(List); Prec.Compute(); // set AztecOO solver object AztecOO AztecOOSolver(Problem); AztecOOSolver.SetAztecOption(AZ_solver,Solver); if (verbose) AztecOOSolver.SetAztecOption(AZ_output,32); else AztecOOSolver.SetAztecOption(AZ_output,AZ_none); AztecOOSolver.SetPrecOperator(&Prec); AztecOOSolver.Iterate(1550,1e-5); return(AztecOOSolver.NumIters()); }
// ====================================================================== bool TestContainer(string Type, const Teuchos::RefCountPtr<Epetra_RowMatrix>& A) { int NumVectors = 3; int NumMyRows = A->NumMyRows(); Epetra_MultiVector LHS_exact(A->RowMatrixRowMap(), NumVectors); Epetra_MultiVector LHS(A->RowMatrixRowMap(), NumVectors); Epetra_MultiVector RHS(A->RowMatrixRowMap(), NumVectors); LHS_exact.Random(); LHS.PutScalar(0.0); A->Multiply(false, LHS_exact, RHS); Epetra_LinearProblem Problem(&*A, &LHS, &RHS); if (verbose) { cout << "Container type = " << Type << endl; cout << "NumMyRows = " << NumMyRows << ", NumVectors = " << NumVectors << endl; } LHS.PutScalar(0.0); Teuchos::RefCountPtr<Ifpack_Container> Container; if (Type == "dense") Container = Teuchos::rcp( new Ifpack_DenseContainer(A->NumMyRows(), NumVectors) ); else Container = Teuchos::rcp( new Ifpack_SparseContainer<Ifpack_Amesos>(A->NumMyRows(), NumVectors) ); assert (Container != Teuchos::null); IFPACK_CHK_ERR(Container->Initialize()); // set as ID all the local rows of A for (int i = 0 ; i < A->NumMyRows() ; ++i) Container->ID(i) = i; // extract submatrix (in this case, the entire matrix) // and complete setup IFPACK_CHK_ERR(Container->Compute(*A)); // set the RHS and LHS for (int i = 0 ; i < A->NumMyRows() ; ++i) for (int j = 0 ; j < NumVectors ; ++j) { Container->RHS(i,j) = RHS[j][i]; Container->LHS(i,j) = LHS[j][i]; } // set parameters (empty for dense containers) Teuchos::ParameterList List; List.set("amesos: solver type", Type); IFPACK_CHK_ERR(Container->SetParameters(List)); // solve the linear system IFPACK_CHK_ERR(Container->ApplyInverse()); // get the computed solution, store it in LHS for (int i = 0 ; i < A->NumMyRows() ; ++i) for (int j = 0 ; j < NumVectors ; ++j) { LHS[j][i] = Container->LHS(i,j); } double residual = Galeri::ComputeNorm(&LHS, &LHS_exact); if (A->Comm().MyPID() == 0 && verbose) { cout << "||x_exact - x||_2 = " << residual << endl; cout << *Container; } bool passed = false; if (residual < 1e-5) passed = true; return(passed); }
void EventLoop(CCam & Camera1) { bool quitit=false; SDL_Event event; SDL_MouseMotionEvent event2; SDL_keysym *whatkey; bool mousedown=false; // Go to while(!quitit) to see what happens once data set up // Go to Render Scene for graphics bit bool exitnow=false; double xunit,yunit,zunit; xunit=1.0;yunit=1.0;zunit=1.0; // if_stream opens for input // of_stream opens for output // f_stream opens for both // string filename ="Sphere4.dat"; ifstream file_in; file_in.open(filename.c_str()); file_in >> n_nodes >> ntri; cout << n_nodes << " number of nodes" << endl; cout << ntri<< " number of triangles" << endl; cout << "read next line\n"; cout << "start read loop\n"; Triangles=(Triangle*)calloc(ntri, sizeof(Triangle)); NodeV=(D3Dvec*)calloc(n_nodes, sizeof(D3Dvec)); //initiales char quad, otherquad; int id,l,m,n; double x,y,z; for(int i=0; i<ntri;i++){ file_in >>l; file_in >>m; file_in >>n; file_in >>quad; // same resuly of file_in >> l >>m >>n; Triangles[i]=Triangle(); //initialise Triangles[i].SetTri(l,m,n); Triangles[i].SetQuad(quad); } for(int i=0; i<ntri;i++){ file_in >> l >> m >> n; Triangles[i].SetNeighb(l,m,n); } for(int i=0; i < n_nodes; i++){ NodeV[i]=D3Dvec(); file_in >> x >> y >> z; NodeV[i].SetVec(x,y,z); } istart=0; istop=ntri; /********************************************************************************** Calculate Metric Tensor **********************************************************************************/ double **Gmetric; Gmetric =(double**)calloc( ntri, sizeof( double[3] ) ); if(!Gmetric){ cout << "Memory Failed for Gmetric " << endl; exit(0);} // 2D vectors in each triangle double **avec, **bvec; avec=(double**)calloc( ntri, sizeof(double[2]) ); if(!avec){ cout << "Memory Failed for avec" << endl; exit(0);} bvec=(double**)calloc( ntri, sizeof(double[2]) ); if(!bvec){ cout << "Memory Failed for bvec" << endl; exit(0);} double avecdash[2], bvecdash[2]; double avecdash_new[2], bvecdash_new[2]; D3Dvec Ve1,Ve2,VOrig; //origin and edge vectors Ve1=D3Dvec(); Ve2=D3Dvec(); VOrig=D3Dvec(); //Initialise D3Dvec Unit_i, Unit_j, Unit_k; Unit_i=D3Dvec(); Unit_j=D3Dvec(); Unit_k=D3Dvec(); int i1,i2,i3; double rad=-1; for(int i=0; i<ntri; i++){ Gmetric[i]=new double[3]; //initialise i1=Triangles[i].Get1(); i2=Triangles[i].Get2(); i3=Triangles[i].Get3(); x=NodeV[i1].GetX(); y=NodeV[i1].GetY(); z=NodeV[i1].GetZ(); VOrig.SetVec(x,y,z); x=NodeV[i2].GetX()-VOrig.GetX(); y=NodeV[i2].GetY()-VOrig.GetY(); z=NodeV[i2].GetZ()-VOrig.GetZ(); Ve1.SetVec(x,y,z); x=NodeV[i3].GetX()-VOrig.GetX(); y=NodeV[i3].GetY()-VOrig.GetY(); z=NodeV[i3].GetZ()-VOrig.GetZ(); Ve2.SetVec(x,y,z); Gmetric[i][0]=Ve1.Dot(Ve1); Gmetric[i][1]=Ve1.Dot(Ve2); Gmetric[i][2]=Ve2.Dot(Ve2); rad=Gmetric[i][0]; rad=sqrt(rad)*6370.; // local cartesians Unit_i=Ve1; Normalise(Unit_i); Unit_k=Ve1*Ve2; Normalise(Unit_k); Unit_j=Unit_k*Unit_i; avec[i]=new double[2]; bvec[i]=new double[2]; avec[i][0]=Unit_i.Dot(Ve1); avec[i][1]=0.0; bvec[i][0]=Unit_i.Dot(Ve2); bvec[i][1]=Unit_j.Dot(Ve2); } /********************************************************************************** GEODESIC- start point **********************************************************************************/ // Now for a geodesic ! // int Tstart0=56; int Tstart, TNext; double xO,yO,zO; double x1,y1,z1; double x2,y2,z2; double x3,y3,z3; char qStart,qNext; double d1, d2, lambda; double d1dash,d2dash; double ds_total, ds_squared; double alpha_start, beta_start; double alphaTstart, betaTstart; //values of lambda to hit the line alpha=0, beta=0, alpha+beta=1 double Tol1=0.000001; // if fabs(d) less than this it lands on edge miles // away or never at all double Tol2=1e-8; //possibility that we land on a corner double alpha_e1, beta_e1; double alpha_e2, beta_e2; double alpha_e3, beta_e3; bool land_e1, land_e2, land_e3; double lambda_edge1, lambda_edge2, lambda_edge3; int Node1, Node2, Node3; double alphaNext,betaNext; double alpha_p, beta_p, alpha_q, beta_q; double alpha_p_dash, beta_p_dash, alpha_q_dash, beta_q_dash; double CosTheta,SinTheta,Theta,Phi; double adot_adash, adot_bdash, bdot_adash, bdot_bdash; double W1,W2,X1,X2,Y1,Y2,Z1,Z2,Det; double ex1,why1,ex2,why3; unsigned int ndim; int kount=0; Tstart=Tstart0; alpha_start=0.25, beta_start=0.25; d1=.25; d2=0.19; bool start_e1, start_e2, start_e3; start_e1=false; //assume that for first triangle start_e2=false; //we don't start off on an edge start_e3=false; //change for instance, if we have alpha_start=0 /********************************************************************************** GEODESIC- Propagate **********************************************************************************/ while(ds_total < 6.3 && kount < GeoPos){ if(kount==GeoPos-1){ cout <<"Last One! " << endl; } Node1=Triangles[Tstart].Get1(); Node2=Triangles[Tstart].Get2(); Node3=Triangles[Tstart].Get3(); D3Dvec Rnode1,Rnode2; Rnode1=D3Dvec(); Rnode2=D3Dvec(); xO=NodeV[Node1].GetX(); yO=NodeV[Node1].GetY(); zO=NodeV[Node1].GetZ(); VOrig.SetVec(xO,yO,zO); x1=NodeV[Node2].GetX(); y1=NodeV[Node2].GetY(); z1=NodeV[Node2].GetZ(); Rnode1.SetVec(x1,y1,z1); x2=NodeV[Node3].GetX(); y2=NodeV[Node3].GetY(); z2=NodeV[Node3].GetZ(); Rnode2.SetVec(x2,y2,z2); Ve1=Rnode1-VOrig; Ve2=Rnode2-VOrig; x3=VOrig.GetX()+alpha_start*Ve1.GetX()+beta_start*Ve2.GetX(); y3=VOrig.GetY()+alpha_start*Ve1.GetY()+beta_start*Ve2.GetY(); z3=VOrig.GetZ()+alpha_start*Ve1.GetZ()+beta_start*Ve2.GetZ(); Geodesy[kount]=new D3Dvec(); Geodesy[kount].SetX(x3); Geodesy[kount].SetY(y3); Geodesy[kount].SetZ(z3); cout << Geodesy[kount].GetX() << " " << Geodesy[kount].GetY() << " " << Geodesy[kount].GetZ() << " kount=" << kount << " Tstart=" << Tstart << endl; kount++; land_e1=false; land_e2=false; land_e3=false; //alpha_start + d1 lambda=0 lands on edge2; //beta_start+ d2 lambda=0 lands on edge1; if( fabs(d1) > Tol1){lambda_edge1=-beta_start/d2; land_e1=true;} if( fabs(d2) > Tol1){lambda_edge2=-alpha_start/d1; land_e2=true;} if( fabs(d2+d2) > Tol1) {lambda_edge3=(1.0-alpha_start-beta_start)/(d1+d2); land_e3=true;} cout << "d1=" << d1 << endl; cout << "d2=" << d2 << endl; cout << "alpha_s=" << alpha_start << endl; cout << "beta_s=" << beta_start << endl; alpha_e1=alpha_start+lambda_edge1*d1; beta_e1=beta_start+lambda_edge1*d2; alpha_e2=alpha_start+lambda_edge2*d1; beta_e2=beta_start+lambda_edge2*d2; alpha_e3=alpha_start+lambda_edge3*d1; beta_e3=beta_start+lambda_edge3*d2; ndim=2; Dmatrix Mat(ndim,ndim); //creates 4 by 3 on the heap. Dvector RHS(ndim); Dvector LHS(ndim); if( (fabs(alpha_e1) < Tol2) && (fabs(beta_e1) <Tol2) ){ // set it safely on edge 1 alpha_e1=2.*Tol2; beta_e1=0.0; } if( (fabs(1.0-alpha_e1) < Tol2) && (fabs(beta_e1) <Tol2) ){ // set it safely on edge 1 alpha_e1=1.0-2.0*Tol2; beta_e1=0.0; } if( (fabs(alpha_e2) < Tol2) && (fabs(beta_e2) <Tol2) ){ // set it safely on edge 2 alpha_e2=0.0; beta_e2=2.0*Tol2; } if( (fabs(1.0-beta_e2) < Tol2) && (fabs(alpha_e2) <Tol2) ){ // set it safely on edge 2 alpha_e2=0.0; beta_e2=1.0-2.0*Tol2; } if( (fabs(1.0-alpha_e3-beta_e3) < Tol2) ){ if(fabs(alpha_e3) < Tol2){ // set it safely on edge 3 alpha_e3=2.0*Tol2; beta_e3=1.0-alpha_e3; } if(fabs(beta_e3) < Tol2){ // set it safely on edge 3 beta_e3=2.0*Tol2; alpha_e3=1.0-beta_e3; } } /* cout << "e1 " << alpha_e1 << " L e1=" << lambda_edge1 << endl; cout << "e2 " << beta_e2 << " L_e2=" << lambda_edge2 << endl; cout << "a e3 " << alpha_e3 << " L_e3=" << lambda_edge3 << endl; cout << "b e3 " << beta_e3 << endl; */ if(lambda_edge1 <0.0 || alpha_e1 < 0.0 || alpha_e1 > 1.0)land_e1=false; if(lambda_edge2 <0.0 || beta_e2 < 0.0 || beta_e2 > 1.0)land_e2=false; if(lambda_edge3 <0.0 || alpha_e3 < 0.0 || alpha_e3 > 1.0)land_e3=false; if(lambda_edge3 <0.0 || beta_e3 < 0.0 || beta_e3 > 1.0)land_e3=false; cout << land_e1 << land_e2 << land_e3 << " edges 1 2 and 3" << endl; // Normally we land on two edges! // We start it some point in the start triangle // proceed to the edge, but now we start at an edge // if(start_e1)land_e1=false; if(start_e2)land_e2=false; if(start_e3)land_e3=false; start_e1=false; start_e2=false; start_e3=false; if(land_e1){ //beta_e1=0 ds_squared= Gmetric[Tstart][0]*(alpha_e1-alpha_start)*(alpha_e1-alpha_start) -2.0*Gmetric[Tstart][1]*(alpha_e1-alpha_start)*beta_start +Gmetric[Tstart][2]*beta_start*beta_start; ds_total=ds_total+sqrt(ds_squared); } if(land_e2){ //alpha_e1=0 ds_squared= Gmetric[Tstart][0]*alpha_start*alpha_start -2.0*Gmetric[Tstart][1]*alpha_start*(beta_e2-beta_start) +Gmetric[Tstart][2]*(beta_e2-beta_start)*(beta_e2-beta_start); ds_total=ds_total+sqrt(ds_squared); } if(land_e3){ ds_squared= Gmetric[Tstart][0]*(alpha_e3-alpha_start)*(alpha_e3-alpha_start) +2.0*Gmetric[Tstart][1]*(alpha_e3-alpha_start)*(beta_e3-beta_start) +Gmetric[Tstart][2]*(beta_e3-beta_start)*(beta_e3-beta_start); ds_total=ds_total+sqrt(ds_squared); } if( land_e1 )TNext=Triangles[Tstart].GetN1(); if( land_e2 )TNext=Triangles[Tstart].GetN2(); if( land_e3 )TNext=Triangles[Tstart].GetN3(); avecdash[0]=avec[TNext][0]; avecdash[1]=avec[TNext][1]; bvecdash[0]=bvec[TNext][0]; bvecdash[1]=bvec[TNext][1]; qStart=Triangles[Tstart].GetQuad(); qNext=Triangles[TNext].GetQuad(); // edge 1 always crosses into an edge 1 in the opposite sense if(land_e1){ alphaNext=1.0-alpha_e1; betaNext=0.0; start_e1=true; alpha_p=0.0; //edge 1 beta_p=0.0; alpha_q=1.0; beta_q=0.0; alpha_p_dash=alpha_q; // same edge, opposite sense beta_p_dash=beta_q; alpha_q_dash=alpha_p; beta_q_dash=beta_p; } // If the neighbour on edge 2 is in a different quad // it lands on edge 3, otherwise minus edge 2 if(land_e2){ alpha_p=0.0; beta_p=0.0; alpha_q=0.0; beta_q=1.0; if(qNext==qStart){ //crosses to edge 2 of neighbour- opposite sense betaNext=1.0-beta_e2; alphaNext=0.0; start_e2=true; alpha_p_dash=alpha_q; beta_p_dash=beta_q; alpha_q_dash=alpha_p; beta_q_dash=beta_p; } else { //crosses to edge 3 of neighbour- same sense. alphaNext=1.0-beta_e2; betaNext=beta_e2; start_e3=true; alpha_p_dash=1.0; beta_p_dash=0.0; alpha_q_dash=0.0; beta_q_dash=1.0; } } if(land_e3){ alpha_p=1.0; beta_p=0.0; alpha_q=0.0; beta_q=1.0; if(qNext==qStart){ //crosses to edge 3 of neighbour- opposite sense. alphaNext=1.0-alpha_e3; betaNext=alpha_e3; alpha_p_dash=alpha_q; beta_p_dash=beta_q; alpha_q_dash=alpha_p; beta_q_dash=beta_p; start_e3=true; } else { //crosses to edge 2 of neighbour -- has same sense alphaNext=0; betaNext=beta_e3; alpha_p_dash=0.0; beta_p_dash=0.0; alpha_q_dash=0.0; beta_q_dash=1.0; start_e2=true; } } cout << "ds_total=" << ds_total << endl; X1=alpha_p_dash*avecdash[0]+beta_p_dash*bvecdash[0]; X2=alpha_p_dash*avecdash[1]+beta_p_dash*bvecdash[1]; Y1=alpha_p*avec[Tstart][0]+beta_p*bvec[Tstart][0]; Y2=alpha_p*avec[Tstart][1]+beta_p*bvec[Tstart][1]; W1=alpha_q_dash*avecdash[0]+beta_q_dash*bvecdash[0]; W2=alpha_q_dash*avecdash[1]+beta_q_dash*bvecdash[1]; Z1=alpha_q*avec[Tstart][0]+beta_q*bvec[Tstart][0]; Z2=alpha_q*avec[Tstart][1]+beta_q*bvec[Tstart][1]; Det=(W2-X2)*(W2-X2)+(W1-X1)*(W1-X1); unsigned int ir,ic,ir1,ir2; ir=0; ic=0; Mat(ir,ic)=W1-X1; ir=0; ic=1; Mat(ir,ic)=W2-X2; ir=1; ic=0; Mat(ir,ic)=-(W2-X2); ir=1; ic=1; Mat(ir,ic)=W1-X1; Mat=Mat/Det; ir=0; RHS(ir)=Z1-Y1; ir=1; RHS(ir)=Z2-Y2; LHS=Mat*RHS; ir=0; CosTheta=LHS(ir); ir=1; SinTheta=LHS(ir); // cout << "cos and sin "<< CosTheta << " " << SinTheta << endl; // cout << "cossq+sinsq=" << CosTheta*CosTheta+SinTheta*SinTheta << endl; avecdash_new[0]= avecdash[0]*CosTheta-avecdash[1]*SinTheta; avecdash_new[1]= avecdash[0]*SinTheta+avecdash[1]*CosTheta; bvecdash_new[0]= bvecdash[0]*CosTheta-bvecdash[1]*SinTheta; bvecdash_new[1]= bvecdash[0]*SinTheta+bvecdash[1]*CosTheta; adot_adash=avec[Tstart][0]*avecdash_new[0] +avec[Tstart][1]*avecdash_new[1]; adot_bdash=avec[Tstart][0]*bvecdash_new[0] +avec[Tstart][1]*bvecdash_new[1]; bdot_adash=bvec[Tstart][0]*avecdash_new[0] +bvec[Tstart][1]*avecdash_new[1]; bdot_bdash=bvec[Tstart][0]*bvecdash_new[0] +bvec[Tstart][1]*bvecdash_new[1]; /* cout << adot_adash << " a dot adash " << avec[Tstart][0]*avecdash_new[0]+ avec[Tstart][1]*avecdash_new[1] << endl; cout << adot_bdash << " a dot bdash " << avec[Tstart][0]*bvecdash_new[0]+ avec[Tstart][1]*bvecdash_new[1] << endl; cout << bdot_adash << " b dot adash " << bvec[Tstart][0]*avecdash_new[0]+ bvec[Tstart][1]*avecdash_new[1] << endl; cout << bdot_bdash << " b dot bdash " << bvec[Tstart][0]*bvecdash_new[0]+ bvec[Tstart][1]*bvecdash_new[1] << endl; */ // The next couts all check out /* cout << " a dot a " << avec[Tstart][0]*avec[Tstart][0]+ avec[Tstart][1]*avec[Tstart][1] << endl; cout << " b dot b " << bvec[Tstart][0]*bvec[Tstart][0]+ bvec[Tstart][1]*bvec[Tstart][1] << endl; cout << " a dot a in Next " << avec[TNext][0]*avec[TNext][0]+ avec[TNext][1]*avec[TNext][1] << endl; cout << bdot_bdash << " b dot b in Next " << bvec[TNext][0]*bvec[TNext][0]+ bvec[TNext][1]*bvec[TNext][1] << endl; cout << "a " << avec[Tstart][0] << " " << avec[Tstart][1] << endl; cout << "b " << bvec[Tstart][0] << " " << bvec[Tstart][1] << endl; */ /* cout << "a dash " << avecdash[0] << " " << avecdash[1] << endl; cout << "b dash " << bvecdash[0] << " " << bvecdash[1] << endl; */ /* cout << "a dash rotate " << avecdash_new[0] << " " << avecdash_new[1] << endl; cout << "b dash rotate " << bvecdash_new[0] << " " << bvecdash_new[1] << endl; */ ir=0;ic=0; Mat(ir,ic)=Gmetric[Tstart][2]; ir=0;ic=1; Mat(ir,ic)=-Gmetric[Tstart][1]; ir=1;ic=0; Mat(ir,ic)=-Gmetric[Tstart][1]; ir=1;ic=1; Mat(ir,ic)=Gmetric[Tstart][0]; Det=Gmetric[Tstart][0]*Gmetric[Tstart][2] -Gmetric[Tstart][1]*Gmetric[Tstart][1]; Mat=Mat/Det; ir=0; RHS(ir)=adot_adash; ir=1; RHS(ir)=bdot_adash; LHS=Mat*RHS; ir=0; x1=LHS(ir); ir=1; y1=LHS(ir); ir=0; RHS(ir)=adot_bdash; ir=1; RHS(ir)=bdot_bdash; LHS=Mat*RHS; ir=0; x2=LHS(ir); ir=1; y2=LHS(ir); //check adash=x1 a + y1 b, bdash=x2 a+ y2 b cout << x1*avec[Tstart][0]+y1*bvec[Tstart][0] << " " << avecdash_new[0] << endl; cout << x1*avec[Tstart][1]+y1*bvec[Tstart][1] << " " << avecdash_new[1] << endl; cout << x2*avec[Tstart][0]+y2*bvec[Tstart][0] << " " << bvecdash_new[0] << endl; cout << x2*avec[Tstart][1]+y2*bvec[Tstart][1] << " " << bvecdash_new[1] << endl; ir=0;ic=0; Mat(ir,ic)=y2; ir=0;ic=1; Mat(ir,ic)=-x2; ir=1;ic=0; Mat(ir,ic)=-y1; ir=1;ic=1; Mat(ir,ic)=x1; Det=x1*y2-x2*y1; Mat=Mat/Det; cout << "M11=" << y2/Det << " M12=" << -x2/Det << endl; cout << "M21=" << -y1/Det << " M12=" << x1/Det << endl; ir=0; RHS(ir)=d1; ir=1; RHS(ir)=d2; LHS=Mat*RHS; ir=0; d1dash=LHS(ir); ir=1; d2dash=LHS(ir); // We have finally arrived in TNext, which will be the new Tstart; Tstart=TNext; alpha_start=alphaNext; beta_start=betaNext; d1=d1dash; d2=d2dash; } //end while ds_total Geokount=kount; cout << "Geokount=" << Geokount << endl; while(!quitit){ while(SDL_PollEvent(&event)){ switch(event.type){ case SDL_QUIT: quitit=true; break; case SDL_MOUSEBUTTONDOWN: mousedown=true; break; case SDL_MOUSEBUTTONUP: mousedown=false; break; case SDL_MOUSEMOTION: if(mousedown){ if(MouseOn)Camera1.MouseView();} else{ if(MouseOn)Camera1.MouseLookAt(); } break; case SDL_KEYDOWN: whatkey=&event.key.keysym; HandleKeyPress(whatkey); break; case SDL_KEYUP: whatkey=&event.key.keysym; HandleKeyRelease(whatkey); default: break; } // end of case } //end of inner loop CheckMove(Camera1); RenderScene(Camera1); } //end of outer loop }
int main(int argc, char *argv[]) { int ierr = 0, i, j, k; #ifdef EPETRA_MPI MPI_Init(&argc,&argv); Epetra_MpiComm Comm( MPI_COMM_WORLD ); #else Epetra_SerialComm Comm; #endif bool verbose = false; // Check if we should print results to standard out if (argc>1) if (argv[1][0]=='-' && argv[1][1]=='v') verbose = true; if(verbose && Comm.MyPID()==0) std::cout << Epetra_Version() << std::endl << std::endl; int rank = Comm.MyPID(); // char tmp; // if (rank==0) std::cout << "Press any key to continue..."<< std::endl; // if (rank==0) cin >> tmp; // Comm.Barrier(); Comm.SetTracebackMode(0); // This should shut down any error traceback reporting if (verbose) std::cout << Comm << std::endl; // bool verbose1 = verbose; // Redefine verbose to only print on PE 0 if (verbose && rank!=0) verbose = false; int N = 20; int NRHS = 4; double * A = new double[N*N]; double * A1 = new double[N*N]; double * X = new double[(N+1)*NRHS]; double * X1 = new double[(N+1)*NRHS]; int LDX = N+1; int LDX1 = N+1; double * B = new double[N*NRHS]; double * B1 = new double[N*NRHS]; int LDB = N; int LDB1 = N; int LDA = N; int LDA1 = LDA; double OneNorm1; bool Upper = false; Epetra_SerialSpdDenseSolver solver; Epetra_SerialSymDenseMatrix * Matrix; for (int kk=0; kk<2; kk++) { for (i=1; i<=N; i++) { GenerateHilbert(A, LDA, i); OneNorm1 = 0.0; for (j=1; j<=i; j++) OneNorm1 += 1.0/((double) j); // 1-Norm = 1 + 1/2 + ...+1/n if (kk==0) { Matrix = new Epetra_SerialSymDenseMatrix(View, A, LDA, i); LDA1 = LDA; } else { Matrix = new Epetra_SerialSymDenseMatrix(Copy, A, LDA, i); LDA1 = i; } GenerateHilbert(A1, LDA1, i); if (kk==1) { solver.FactorWithEquilibration(true); Matrix->SetUpper(); Upper = true; solver.SolveToRefinedSolution(false); } for (k=0; k<NRHS; k++) for (j=0; j<i; j++) { B[j+k*LDB] = 1.0/((double) (k+3)*(j+3)); B1[j+k*LDB1] = B[j+k*LDB1]; } Epetra_SerialDenseMatrix Epetra_B(View, B, LDB, i, NRHS); Epetra_SerialDenseMatrix Epetra_X(View, X, LDX, i, NRHS); solver.SetMatrix(*Matrix); solver.SetVectors(Epetra_X, Epetra_B); ierr = check(solver, A1, LDA1, i, NRHS, OneNorm1, B1, LDB1, X1, LDX1, Upper, verbose); assert (ierr>-1); delete Matrix; if (ierr!=0) { if (verbose) std::cout << "Factorization failed due to bad conditioning. This is normal if SCOND is small." << std::endl; break; } } } delete [] A; delete [] A1; delete [] X; delete [] X1; delete [] B; delete [] B1; ///////////////////////////////////////////////////////////////////// // Now test norms and scaling functions ///////////////////////////////////////////////////////////////////// Epetra_SerialSymDenseMatrix D; double ScalarA = 2.0; int DM = 10; int DN = 10; D.Shape(DM); for (j=0; j<DN; j++) for (i=0; i<DM; i++) D[j][i] = (double) (1+i+j*DM) ; //std::cout << D << std::endl; double NormInfD_ref = (double)(DM*(DN*(DN+1))/2); double NormOneD_ref = NormInfD_ref; double NormInfD = D.NormInf(); double NormOneD = D.NormOne(); if (verbose) { std::cout << " *** Before scaling *** " << std::endl << " Computed one-norm of test matrix = " << NormOneD << std::endl << " Expected one-norm = " << NormOneD_ref << std::endl << " Computed inf-norm of test matrix = " << NormInfD << std::endl << " Expected inf-norm = " << NormInfD_ref << std::endl; } D.Scale(ScalarA); // Scale entire D matrix by this value //std::cout << D << std::endl; NormInfD = D.NormInf(); NormOneD = D.NormOne(); if (verbose) { std::cout << " *** After scaling *** " << std::endl << " Computed one-norm of test matrix = " << NormOneD << std::endl << " Expected one-norm = " << NormOneD_ref*ScalarA << std::endl << " Computed inf-norm of test matrix = " << NormInfD << std::endl << " Expected inf-norm = " << NormInfD_ref*ScalarA << std::endl; } ///////////////////////////////////////////////////////////////////// // Now test for larger system, both correctness and performance. ///////////////////////////////////////////////////////////////////// N = 2000; NRHS = 5; LDA = N; LDB = N; LDX = N; if (verbose) std::cout << "\n\nComputing factor of an " << N << " x " << N << " SPD matrix...Please wait.\n\n" << std::endl; // Define A and X A = new double[LDA*N]; X = new double[LDB*NRHS]; for (j=0; j<N; j++) { for (k=0; k<NRHS; k++) X[j+k*LDX] = 1.0/((double) (j+5+k)); for (i=0; i<N; i++) { if (i==j) A[i+j*LDA] = 100.0 + i; else A[i+j*LDA] = -1.0/((double) (i+10)*(j+10)); } } // Define Epetra_SerialDenseMatrix object Epetra_SerialSymDenseMatrix BigMatrix(Copy, A, LDA, N); Epetra_SerialSymDenseMatrix OrigBigMatrix(View, A, LDA, N); Epetra_SerialSpdDenseSolver BigSolver; BigSolver.FactorWithEquilibration(true); BigSolver.SetMatrix(BigMatrix); // Time factorization Epetra_Flops counter; BigSolver.SetFlopCounter(counter); Epetra_Time Timer(Comm); double tstart = Timer.ElapsedTime(); ierr = BigSolver.Factor(); if (ierr!=0 && verbose) std::cout << "Error in factorization = "<<ierr<< std::endl; assert(ierr==0); double time = Timer.ElapsedTime() - tstart; double FLOPS = counter.Flops(); double MFLOPS = FLOPS/time/1000000.0; if (verbose) std::cout << "MFLOPS for Factorization = " << MFLOPS << std::endl; // Define Left hand side and right hand side Epetra_SerialDenseMatrix LHS(View, X, LDX, N, NRHS); Epetra_SerialDenseMatrix RHS; RHS.Shape(N,NRHS); // Allocate RHS // Compute RHS from A and X Epetra_Flops RHS_counter; RHS.SetFlopCounter(RHS_counter); tstart = Timer.ElapsedTime(); RHS.Multiply('L', 1.0, OrigBigMatrix, LHS, 0.0); // Symmetric Matrix-multiply time = Timer.ElapsedTime() - tstart; Epetra_SerialDenseMatrix OrigRHS = RHS; FLOPS = RHS_counter.Flops(); MFLOPS = FLOPS/time/1000000.0; if (verbose) std::cout << "MFLOPS to build RHS (NRHS = " << NRHS <<") = " << MFLOPS << std::endl; // Set LHS and RHS and solve BigSolver.SetVectors(LHS, RHS); tstart = Timer.ElapsedTime(); ierr = BigSolver.Solve(); if (ierr==1 && verbose) std::cout << "LAPACK guidelines suggest this matrix might benefit from equilibration." << std::endl; else if (ierr!=0 && verbose) std::cout << "Error in solve = "<<ierr<< std::endl; assert(ierr>=0); time = Timer.ElapsedTime() - tstart; FLOPS = BigSolver.Flops(); MFLOPS = FLOPS/time/1000000.0; if (verbose) std::cout << "MFLOPS for Solve (NRHS = " << NRHS <<") = " << MFLOPS << std::endl; double * resid = new double[NRHS]; bool OK = Residual(N, NRHS, A, LDA, BigSolver.X(), BigSolver.LDX(), OrigRHS.A(), OrigRHS.LDA(), resid); if (verbose) { if (!OK) std::cout << "************* Residual do not meet tolerance *************" << std::endl; for (i=0; i<NRHS; i++) std::cout << "Residual[" << i <<"] = "<< resid[i] << std::endl; std::cout << std::endl; } // Solve again using the Epetra_SerialDenseVector class for LHS and RHS Epetra_SerialDenseVector X2; Epetra_SerialDenseVector B2; X2.Size(BigMatrix.N()); B2.Size(BigMatrix.M()); int length = BigMatrix.N(); {for (int kk=0; kk<length; kk++) X2[kk] = ((double ) kk)/ ((double) length);} // Define entries of X2 RHS_counter.ResetFlops(); B2.SetFlopCounter(RHS_counter); tstart = Timer.ElapsedTime(); B2.Multiply('N', 'N', 1.0, OrigBigMatrix, X2, 0.0); // Define B2 = A*X2 time = Timer.ElapsedTime() - tstart; Epetra_SerialDenseVector OrigB2 = B2; FLOPS = RHS_counter.Flops(); MFLOPS = FLOPS/time/1000000.0; if (verbose) std::cout << "MFLOPS to build single RHS = " << MFLOPS << std::endl; // Set LHS and RHS and solve BigSolver.SetVectors(X2, B2); tstart = Timer.ElapsedTime(); ierr = BigSolver.Solve(); time = Timer.ElapsedTime() - tstart; if (ierr==1 && verbose) std::cout << "LAPACK guidelines suggest this matrix might benefit from equilibration." << std::endl; else if (ierr!=0 && verbose) std::cout << "Error in solve = "<<ierr<< std::endl; assert(ierr>=0); FLOPS = counter.Flops(); MFLOPS = FLOPS/time/1000000.0; if (verbose) std::cout << "MFLOPS to solve single RHS = " << MFLOPS << std::endl; OK = Residual(N, 1, A, LDA, BigSolver.X(), BigSolver.LDX(), OrigB2.A(), OrigB2.LDA(), resid); if (verbose) { if (!OK) std::cout << "************* Residual do not meet tolerance *************" << std::endl; std::cout << "Residual = "<< resid[0] << std::endl; } delete [] resid; delete [] A; delete [] X; /////////////////////////////////////////////////// // Now test default constructor and index operators /////////////////////////////////////////////////// N = 5; Epetra_SerialSymDenseMatrix C; // Implicit call to default constructor, should not need to call destructor C.Shape(5); // Make it 5 by 5 double * C1 = new double[N*N]; GenerateHilbert(C1, N, N); // Generate Hilber matrix C1[1+2*N] = 1000.0; // Make matrix nonsymmetric // Fill values of C with Hilbert values for (i=0; i<N; i++) for (j=0; j<N; j++) C(i,j) = C1[i+j*N]; // Test if values are correctly written and read for (i=0; i<N; i++) for (j=0; j<N; j++) { assert(C(i,j) == C1[i+j*N]); assert(C(i,j) == C[j][i]); } if (verbose) std::cout << "Default constructor and index operator check OK. Values of Hilbert matrix = " << std::endl << C << std::endl << "Values should be 1/(i+j+1), except value (1,2) should be 1000" << std::endl; delete [] C1; #ifdef EPETRA_MPI MPI_Finalize() ; #endif /* end main */ return ierr ; }
QRect CEdge::drawTree( Q3Canvas* canvas, int left, int depth, StringToString* filter ) { int X_PADDING = 10; int Y_SPACING = 30; // int X_MARGIN = 10; unused variable 'X_Margin' int Y_MARGIN = 10; //================================================ Q3CanvasItem* edge = new Q3CanvasText( LHS(), canvas ), * leaf = NULL; Q3CanvasLine* line; m_CanvasItems.clear(); m_CanvasItems.append( edge ); int myLeft = left, myTop = ( depth * Y_SPACING ) + Y_MARGIN, myCenterX, myBottom, childCenterX, childLeft, childTop, shiftAmount; Q3ValueList<QRect> daughterBoundingRectangles; Q3ValueList<QRect>::iterator it; QRect myBoundingRect, rectangle; myBoundingRect.setTop( myTop ); myBoundingRect.setLeft( myLeft ); myBoundingRect.setBottom( myTop + edge->boundingRect().height() - 1 ); myBoundingRect.setRight( myLeft + edge->boundingRect().width() - 1 ); int count = 0; // bool first = TRUE; unused variable 'first' CEdge* daughter; for( daughter = m_Daughters.first(); daughter; daughter = m_Daughters.next() ) { daughterBoundingRectangles.append( rectangle ); daughterBoundingRectangles[count] = daughter->drawTree( canvas, left, depth + 1, filter ); // Adjust left position based on bounding rectangle of last daughter left = daughterBoundingRectangles[count].right() + X_PADDING; count++; } if( m_Daughters.isEmpty() ) { // Create leaf node childLeft = myLeft; childTop = ( ( depth + 1 ) * Y_SPACING ) + Y_MARGIN; leaf = new Q3CanvasText( Filter( filter, RHS() ), canvas ); m_CanvasItems.append( leaf ); leaf->move( childLeft, childTop ); leaf->show(); // Adjust my bounding rect if( leaf->boundingRect().right() > myBoundingRect.right() ) myBoundingRect.setRight( leaf->boundingRect().right() ); myBoundingRect.setBottom( leaf->boundingRect().bottom() ); } else { for( it = daughterBoundingRectangles.begin(); it != daughterBoundingRectangles.end(); ++it ) { // Adjust my bounding rect if( (*it).right() > myBoundingRect.right() ) myBoundingRect.setRight( (*it).right() ); if( (*it).bottom() > myBoundingRect.bottom() ) myBoundingRect.setBottom( (*it).bottom() ); } } if( myBoundingRect.width() == edge->boundingRect().width() ) { // Shift all children to the right if( m_Daughters.isEmpty() ) { shiftAmount = int (( myBoundingRect.width() - leaf->boundingRect().width() ) / 2.0); leaf->move( leaf->boundingRect().left() + shiftAmount, leaf->boundingRect().top() ); leaf->show(); } else { shiftAmount = int (( myBoundingRect.width() - ( daughterBoundingRectangles.last().right() - daughterBoundingRectangles.first().left() ) ) / 2.0); for( daughter = m_Daughters.first(); daughter; daughter = m_Daughters.next() ) { daughter->shiftTree( canvas, shiftAmount, 0 ); } for( it = daughterBoundingRectangles.begin(); it != daughterBoundingRectangles.end(); ++it ) { // Adjust the bounding rect position (*it).setLeft( (*it).left() + shiftAmount ); (*it).setRight( (*it).right() + shiftAmount ); } } } else myLeft = ( myBoundingRect.right() - ( myBoundingRect.width() / 2 ) ) - ( edge->boundingRect().width() / 2 ); if( myLeft < myBoundingRect.left() ) myLeft = myBoundingRect.left(); edge->move( myLeft, myTop ); // Draw lines to daughter nodes if( m_Daughters.isEmpty() ) { myCenterX = edge->boundingRect().center().x(); myBottom = edge->boundingRect().bottom(); childCenterX = leaf->boundingRect().center().x(); childTop = leaf->boundingRect().top(); if( myCenterX - childCenterX == 1 || myCenterX - childCenterX == -1 ) myCenterX = childCenterX; line = new Q3CanvasLine( canvas ); line->setPoints( myCenterX, myBottom, childCenterX, childTop ); line->show(); m_CanvasItems.append( line ); } else { Q3ValueList<QRect>::iterator it; for( it = daughterBoundingRectangles.begin(); it != daughterBoundingRectangles.end(); ++it ) { myCenterX = edge->boundingRect().center().x(); myBottom = edge->boundingRect().bottom(); childCenterX = (*it).center().x(); childTop = (*it).top(); if( myCenterX - childCenterX == 1 || myCenterX - childCenterX == -1 ) myCenterX = childCenterX; line = new Q3CanvasLine( canvas ); line->setPoints( myCenterX, myBottom, childCenterX, childTop ); line->show(); m_CanvasItems.append( line ); } } edge->show(); canvas->update(); return myBoundingRect; }
// ====================================================================== bool KrylovTest(string PrecType, const Teuchos::RefCountPtr<Epetra_RowMatrix>& A, bool backward, bool reorder=false) { Epetra_MultiVector LHS(A->RowMatrixRowMap(), NumVectors); Epetra_MultiVector RHS(A->RowMatrixRowMap(), NumVectors); LHS.PutScalar(0.0); RHS.Random(); Epetra_LinearProblem Problem(&*A, &LHS, &RHS); // Set up the list Teuchos::ParameterList List; List.set("relaxation: damping factor", 1.0); List.set("relaxation: type", PrecType); if(backward) List.set("relaxation: backward mode",backward); // Reordering if needed int NumRows=A->NumMyRows(); std::vector<int> RowList(NumRows); if(reorder) { for(int i=0; i<NumRows; i++) RowList[i]=i; List.set("relaxation: number of local smoothing indices",NumRows); List.set("relaxation: local smoothing indices",RowList.size()>0? &RowList[0] : (int*)0); } int Iters1, Iters10; if (verbose) { cout << "Krylov test: Using " << PrecType << " with AztecOO" << endl; } // ============================================== // // get the number of iterations with 1 sweep only // // ============================================== // { List.set("relaxation: sweeps",1); Ifpack_PointRelaxation Point(&*A); Point.SetParameters(List); Point.Compute(); // set AztecOO solver object AztecOO AztecOOSolver(Problem); AztecOOSolver.SetAztecOption(AZ_solver,Solver); AztecOOSolver.SetAztecOption(AZ_output,AZ_none); AztecOOSolver.SetPrecOperator(&Point); AztecOOSolver.Iterate(2550,1e-5); double TrueResidual = AztecOOSolver.TrueResidual(); // some output if (verbose && Problem.GetMatrix()->Comm().MyPID() == 0) { cout << "Norm of the true residual = " << TrueResidual << endl; } Iters1 = AztecOOSolver.NumIters(); } // ======================================================== // // now re-run with 10 sweeps, solver should converge faster // ======================================================== // { List.set("relaxation: sweeps",10); Ifpack_PointRelaxation Point(&*A); Point.SetParameters(List); Point.Compute(); LHS.PutScalar(0.0); // set AztecOO solver object AztecOO AztecOOSolver(Problem); AztecOOSolver.SetAztecOption(AZ_solver,Solver); AztecOOSolver.SetAztecOption(AZ_output,AZ_none); AztecOOSolver.SetPrecOperator(&Point); AztecOOSolver.Iterate(2550,1e-5); double TrueResidual = AztecOOSolver.TrueResidual(); // some output if (verbose && Problem.GetMatrix()->Comm().MyPID() == 0) { cout << "Norm of the true residual = " << TrueResidual << endl; } Iters10 = AztecOOSolver.NumIters(); } if (verbose) { cout << "Iters_1 = " << Iters1 << ", Iters_10 = " << Iters10 << endl; cout << "(second number should be smaller than first one)" << endl; } if (Iters10 > Iters1) { if (verbose) cout << "KrylovTest TEST FAILED!" << endl; return(false); } else { if (verbose) cout << "KrylovTest TEST PASSED" << endl; return(true); } }
// A second pass deriving better H from previous H is worthwhile. // More such passes gain nothing for the extra compute time. // void MHmgphy::HmgphyFromHmgphy( vector<double> &X, int nTr ) { double sc = 2 * max( gW, gH ); int nvars = nTr * NX; printf( "Hmg: %d unknowns; %d constraints.\n", nvars, vAllC.size() ); vector<double> RHS( nvars, 0.0 ); vector<LHSCol> LHS( nvars ); X.resize( nvars ); // Apply previous final results at highest level, once only SetUniteLayer( LHS, RHS, sc ); // Get the Homographies A vector<double> A; HmgphyFromAffine( A, nTr ); // SetPointPairs: H(pi) = A(pj) double fz = 1.0; int nc = vAllC.size(); for( int i = 0; i < nc; ++i ) { const Constraint &C = vAllC[i]; if( !C.used || !C.inlier ) continue; // H(p1) = A(p2) { int j = vRgn[C.r1].itr * NX; double x1 = C.p1.x * fz / sc, y1 = C.p1.y * fz / sc, x2, y2; Point g2 = C.p2; L2GPoint( g2, A, vRgn[C.r2].itr ); x2 = g2.x / sc; y2 = g2.y / sc; double v[5] = { x1, y1, fz, -x1*x2, -y1*x2 }; int i1[5] = { j, j+1, j+2, j+6, j+7 }, i2[5] = { j+3, j+4, j+5, j+6, j+7 }; AddConstraint( LHS, RHS, 5, i1, v, x2 * fz ); v[3] = -x1*y2; v[4] = -y1*y2; AddConstraint( LHS, RHS, 5, i2, v, y2 * fz ); } // H(p2) = A(p1) { int j = vRgn[C.r2].itr * NX; double x1 = C.p2.x * fz / sc, y1 = C.p2.y * fz / sc, x2, y2; Point g2 = C.p1; L2GPoint( g2, A, vRgn[C.r1].itr ); x2 = g2.x / sc; y2 = g2.y / sc; double v[5] = { x1, y1, fz, -x1*x2, -y1*x2 }; int i1[5] = { j, j+1, j+2, j+6, j+7 }, i2[5] = { j+3, j+4, j+5, j+6, j+7 }; AddConstraint( LHS, RHS, 5, i1, v, x2 * fz ); v[3] = -x1*y2; v[4] = -y1*y2; AddConstraint( LHS, RHS, 5, i2, v, y2 * fz ); } } // Solve WriteSolveRead( X, LHS, RHS, "H-FrmH", nproc, false ); PrintMagnitude( X ); RescaleAll( X, sc ); }
int main(int argc, char *argv[]) { // initialize MPI and Epetra communicator #ifdef HAVE_MPI MPI_Init(&argc,&argv); Epetra_MpiComm Comm( MPI_COMM_WORLD ); #else Epetra_SerialComm Comm; #endif Teuchos::ParameterList GaleriList; // The problem is defined on a 2D grid, global size is nx * nx. int nx = 30; GaleriList.set("nx", nx); GaleriList.set("ny", nx * Comm.NumProc()); GaleriList.set("mx", 1); GaleriList.set("my", Comm.NumProc()); Teuchos::RefCountPtr<Epetra_Map> Map = Teuchos::rcp( Galeri::CreateMap64("Cartesian2D", Comm, GaleriList) ); Teuchos::RefCountPtr<Epetra_RowMatrix> A = Teuchos::rcp( Galeri::CreateCrsMatrix("Laplace2D", &*Map, GaleriList) ); // =============================================================== // // B E G I N N I N G O F I F P A C K C O N S T R U C T I O N // // =============================================================== // Teuchos::ParameterList List; // builds an Ifpack_AdditiveSchwarz. This is templated with // the local solvers, in this case Ifpack_BlockRelaxation. // Ifpack_BlockRelaxation requires as a templated a container // class. A container defines // how to store the diagonal blocks. Two choices are available: // Ifpack_DenseContainer (to store them as dense block, // than use LAPACK' factorization to apply the inverse of // each block), of Ifpack_SparseContainer (to store // the diagonal block as Epetra_CrsMatrix's). // // Here, we use Ifpack_SparseContainer, which in turn is // templated with the class to use to apply the inverse // of each block. For example, we can use Ifpack_Amesos. // We still have to decide the overlap among the processes, // and the overlap among the blocks. The two values // can be different. The overlap among the blocks is // considered only if block Jacobi is used. int OverlapProcs = 2; int OverlapBlocks = 0; // define the block below to use dense containers #if 0 Ifpack_AdditiveSchwarz<Ifpack_BlockRelaxation<Ifpack_DenseContainer> > Prec(A, OverlapProcs); #else Ifpack_AdditiveSchwarz<Ifpack_BlockRelaxation<Ifpack_SparseContainer<Ifpack_Amesos> > > Prec(&*A, OverlapProcs); #endif List.set("relaxation: type", "symmetric Gauss-Seidel"); List.set("partitioner: overlap", OverlapBlocks); #ifdef HAVE_IFPACK_METIS // use METIS to create the blocks. This requires --enable-ifpack-metis. // If METIS is not installed, the user may select "linear". List.set("partitioner: type", "metis"); #else // or a simple greedy algorithm is METIS is not enabled List.set("partitioner: type", "greedy"); #endif // defines here the number of local blocks. If 1, // and only one process is used in the computation, then // the preconditioner must converge in one iteration. List.set("partitioner: local parts", 4); // sets the parameters IFPACK_CHK_ERR(Prec.SetParameters(List)); // initialize the preconditioner. IFPACK_CHK_ERR(Prec.Initialize()); // Builds the preconditioners. IFPACK_CHK_ERR(Prec.Compute()); // =================================================== // // E N D O F I F P A C K C O N S T R U C T I O N // // =================================================== // // At this point, we need some additional objects // to define and solve the linear system. // defines LHS and RHS Epetra_Vector LHS(A->OperatorDomainMap()); Epetra_Vector RHS(A->OperatorDomainMap()); LHS.PutScalar(0.0); RHS.Random(); // need an Epetra_LinearProblem to define AztecOO solver Epetra_LinearProblem Problem(&*A,&LHS,&RHS); // now we can allocate the AztecOO solver AztecOO Solver(Problem); // specify solver Solver.SetAztecOption(AZ_solver,AZ_cg); Solver.SetAztecOption(AZ_output,32); // HERE WE SET THE IFPACK PRECONDITIONER Solver.SetPrecOperator(&Prec); // .. and here we solve // NOTE: with one process, the solver must converge in // one iteration. Solver.Iterate(1550,1e-5); #ifdef HAVE_MPI MPI_Finalize() ; #endif return(EXIT_SUCCESS); }
// Experiment to use approximations H(pi) = T(pj). In practice // translations lack the accuracy of affines and are always an // inferior starting point for homographies. // void MHmgphy::HmgphyFromTrans( vector<double> &X, int nTr ) { double sc = 2 * max( gW, gH ); int nvars = nTr * NX; printf( "Hmg: %d unknowns; %d constraints.\n", nvars, vAllC.size() ); vector<double> RHS( nvars, 0.0 ); vector<LHSCol> LHS( nvars ); X.resize( nvars ); // Get the pure translations T MTrans M; vector<double> T; M.SetModelParams( gW, gH, -1, -1, -1, -1, nproc, -1, NULL, NULL, zs ); M.SolveSystem( T, nTr ); // SetPointPairs: H(pi) = T(pj) double fz = 1.0; int nc = vAllC.size(); for( int i = 0; i < nc; ++i ) { const Constraint &C = vAllC[i]; if( !C.used || !C.inlier ) continue; // H(p1) = T(p2) { int j = vRgn[C.r1].itr * NX, k = vRgn[C.r2].itr * 2; double x1 = C.p1.x * fz / sc, y1 = C.p1.y * fz / sc, x2 = (C.p2.x + T[k ]) / sc, y2 = (C.p2.y + T[k+1]) / sc; double v[5] = { x1, y1, fz, -x1*x2, -y1*x2 }; int i1[5] = { j, j+1, j+2, j+6, j+7 }, i2[5] = { j+3, j+4, j+5, j+6, j+7 }; AddConstraint( LHS, RHS, 5, i1, v, x2 * fz ); v[3] = -x1*y2; v[4] = -y1*y2; AddConstraint( LHS, RHS, 5, i2, v, y2 * fz ); } // H(p2) = T(p1) { int j = vRgn[C.r2].itr * NX, k = vRgn[C.r1].itr * 2; double x1 = C.p2.x * fz / sc, y1 = C.p2.y * fz / sc, x2 = (C.p1.x + T[k ]) / sc, y2 = (C.p1.y + T[k+1]) / sc; double v[5] = { x1, y1, fz, -x1*x2, -y1*x2 }; int i1[5] = { j, j+1, j+2, j+6, j+7 }, i2[5] = { j+3, j+4, j+5, j+6, j+7 }; AddConstraint( LHS, RHS, 5, i1, v, x2 * fz ); v[3] = -x1*y2; v[4] = -y1*y2; AddConstraint( LHS, RHS, 5, i2, v, y2 * fz ); } } // Solve WriteSolveRead( X, LHS, RHS, "H-FrmT", nproc, false ); PrintMagnitude( X ); RescaleAll( X, sc ); }
// Like AffineFromAffine, try another pass of scaffold refinement. // void MAffine::AffineFromAffine2( vector<double> &X, int nTr ) { double sc = 2 * max( gW, gH ); int nvars = nTr * NX; printf( "Aff: %d unknowns; %d constraints.\n", nvars, vAllC.size() ); vector<double> RHS( nvars, 0.0 ); vector<LHSCol> LHS( nvars ); X.resize( nvars ); // Get the Affines A vector<double> A; AffineFromAffine( A, nTr ); // SetPointPairs: A(pi) = A(pj) double fz = 1.0; int nc = vAllC.size(); for( int i = 0; i < nc; ++i ) { const Constraint &C = vAllC[i]; if( !C.used || !C.inlier ) continue; // A(p1) = A(p2) { int j = vRgn[C.r1].itr * NX; double x1 = C.p1.x * fz / sc, y1 = C.p1.y * fz / sc, x2, y2; Point g2 = C.p2; L2GPoint( g2, A, vRgn[C.r2].itr ); x2 = g2.x * fz / sc; y2 = g2.y * fz / sc; double v[3] = { x1, y1, fz }; int i1[3] = { j, j+1, j+2 }, i2[3] = { j+3, j+4, j+5 }; AddConstraint( LHS, RHS, 3, i1, v, x2 ); AddConstraint( LHS, RHS, 3, i2, v, y2 ); } // A(p2) = T(p1) { int j = vRgn[C.r2].itr * NX; double x1 = C.p2.x * fz / sc, y1 = C.p2.y * fz / sc, x2, y2; Point g2 = C.p1; L2GPoint( g2, A, vRgn[C.r1].itr ); x2 = g2.x * fz / sc; y2 = g2.y * fz / sc; double v[3] = { x1, y1, fz }; int i1[3] = { j, j+1, j+2 }, i2[3] = { j+3, j+4, j+5 }; AddConstraint( LHS, RHS, 3, i1, v, x2 ); AddConstraint( LHS, RHS, 3, i2, v, y2 ); } } // Solve //SolveWithSquareness( X, LHS, RHS, nTr ); //SolveWithUnitMag( X, LHS, RHS, nTr ); WriteSolveRead( X, LHS, RHS, "A-FrmA2", nproc, false ); PrintMagnitude( X ); RescaleAll( X, sc ); }
// This method for solving montages omits calling SetPointPairs // to assert A1(p1) - A2(p2). Rather, we only set approximations // A(pi) = T(pj). This isn't nearly as accurate as the current // favorite AffineFromTransWt, which combines SetPointPairs with // downweighted scaffold constraints A(pi) = T(pj). // // Rather than give up on this method, I also tried to improve // results by a series of scaffold refinements. That is, first // get T's, use those to get A's, use those to get better A's // do that again. The result of that slowly converges toward // AffineFromTransWt but a great computaion cost. These iterative // experiment snippets follow. // void MAffine::AffineFromTrans( vector<double> &X, int nTr ) { double sc = 2 * max( gW, gH ); int nvars = nTr * NX; printf( "Aff: %d unknowns; %d constraints.\n", nvars, vAllC.size() ); vector<double> RHS( nvars, 0.0 ); vector<LHSCol> LHS( nvars ); X.resize( nvars ); // Get the pure translations T MTrans M; vector<double> T; M.SetModelParams( gW, gH, -1, -1, -1, -1, nproc, -1, NULL, NULL, zs ); M.SolveSystem( T, nTr ); // SetPointPairs: A(pi) = T(pj) int nc = vAllC.size(); for( int i = 0; i < nc; ++i ) { const Constraint &C = vAllC[i]; if( !C.used || !C.inlier ) continue; // A(p1) = T(p2) { int j = vRgn[C.r1].itr * NX, k = vRgn[C.r2].itr * 2; double x1 = C.p1.x * scaf_strength / sc, y1 = C.p1.y * scaf_strength / sc, x2 = (C.p2.x + T[k ]) * scaf_strength / sc, y2 = (C.p2.y + T[k+1]) * scaf_strength / sc; double v[3] = { x1, y1, scaf_strength }; int i1[3] = { j, j+1, j+2 }, i2[3] = { j+3, j+4, j+5 }; AddConstraint( LHS, RHS, 3, i1, v, x2 ); AddConstraint( LHS, RHS, 3, i2, v, y2 ); } // A(p2) = T(p1) { int j = vRgn[C.r2].itr * NX, k = vRgn[C.r1].itr * 2; double x1 = C.p2.x * scaf_strength / sc, y1 = C.p2.y * scaf_strength / sc, x2 = (C.p1.x + T[k ]) * scaf_strength / sc, y2 = (C.p1.y + T[k+1]) * scaf_strength / sc; double v[3] = { x1, y1, scaf_strength }; int i1[3] = { j, j+1, j+2 }, i2[3] = { j+3, j+4, j+5 }; AddConstraint( LHS, RHS, 3, i1, v, x2 ); AddConstraint( LHS, RHS, 3, i2, v, y2 ); } } // Solve //SolveWithSquareness( X, LHS, RHS, nTr ); //SolveWithUnitMag( X, LHS, RHS, nTr ); WriteSolveRead( X, LHS, RHS, "A-FrmT", nproc, false ); PrintMagnitude( X ); RescaleAll( X, sc ); }
int main(int argc, char *argv[]) { // initialize MPI and Epetra communicator #ifdef HAVE_MPI MPI_Init(&argc,&argv); Epetra_MpiComm Comm( MPI_COMM_WORLD ); #else Epetra_SerialComm Comm; #endif Teuchos::ParameterList GaleriList; // The problem is defined on a 2D grid, global size is nx * nx. int nx = 30; GaleriList.set("nx", nx); GaleriList.set("ny", nx * Comm.NumProc()); GaleriList.set("mx", 1); GaleriList.set("my", Comm.NumProc()); Teuchos::RefCountPtr<Epetra_Map> Map = Teuchos::rcp( Galeri::CreateMap64("Cartesian2D", Comm, GaleriList) ); Teuchos::RefCountPtr<Epetra_RowMatrix> A = Teuchos::rcp( Galeri::CreateCrsMatrix("Laplace2D", &*Map, GaleriList) ); // =============================================================== // // B E G I N N I N G O F I F P A C K C O N S T R U C T I O N // // =============================================================== // Teuchos::ParameterList List; // builds an Ifpack_AdditiveSchwarz. This is templated with // the local solvers, in this case Ifpack_ICT. Note that any // other Ifpack_Preconditioner-derived class can be used // instead of Ifpack_ICT. // In this example the overlap is zero. Use // Prec(A,OverlapLevel) for the general case. Ifpack_AdditiveSchwarz<Ifpack_ICT> Prec(&*A); // `1.0' means that the factorization should approximatively // keep the same number of nonzeros per row of the original matrix. List.set("fact: ict level-of-fill", 1.0); // no modifications on the diagonal List.set("fact: absolute threshold", 0.0); List.set("fact: relative threshold", 1.0); List.set("fact: relaxation value", 0.0); // matrix `laplace_2d_bc' is not symmetric because of the way // boundary conditions are imposed. We can filter the singletons, // (that is, Dirichlet nodes) and end up with a symmetric // matrix (as ICT requires). List.set("schwarz: filter singletons", true); // sets the parameters IFPACK_CHK_ERR(Prec.SetParameters(List)); // initialize the preconditioner. At this point the matrix must // have been FillComplete()'d, but actual values are ignored. IFPACK_CHK_ERR(Prec.Initialize()); // Builds the preconditioners, by looking for the values of // the matrix. IFPACK_CHK_ERR(Prec.Compute()); // =================================================== // // E N D O F I F P A C K C O N S T R U C T I O N // // =================================================== // // At this point, we need some additional objects // to define and solve the linear system. // defines LHS and RHS Epetra_Vector LHS(A->OperatorDomainMap()); Epetra_Vector RHS(A->OperatorDomainMap()); LHS.PutScalar(0.0); RHS.Random(); // need an Epetra_LinearProblem to define AztecOO solver Epetra_LinearProblem Problem(&*A,&LHS,&RHS); // now we can allocate the AztecOO solver AztecOO Solver(Problem); // specify solver Solver.SetAztecOption(AZ_solver,AZ_cg_condnum); Solver.SetAztecOption(AZ_output,32); // HERE WE SET THE IFPACK PRECONDITIONER Solver.SetPrecOperator(&Prec); // .. and here we solve // NOTE: with one process, the solver must converge in // one iteration. Solver.Iterate(1550,1e-5); // Prints out some information about the preconditioner cout << Prec; #ifdef HAVE_MPI MPI_Finalize(); #endif return (EXIT_SUCCESS); }
//========================================================================== int Ifpack_ICT::Compute() { if (!IsInitialized()) IFPACK_CHK_ERR(Initialize()); Time_.ResetStartTime(); IsComputed_ = false; NumMyRows_ = A_.NumMyRows(); int Length = A_.MaxNumEntries(); vector<int> RowIndices(Length); vector<double> RowValues(Length); bool distributed = (Comm().NumProc() > 1)?true:false; if (distributed) { SerialComm_ = Teuchos::rcp(new Epetra_SerialComm); SerialMap_ = Teuchos::rcp(new Epetra_Map(NumMyRows_, 0, *SerialComm_)); assert (SerialComm_.get() != 0); assert (SerialMap_.get() != 0); } else SerialMap_ = Teuchos::rcp(const_cast<Epetra_Map*>(&A_.RowMatrixRowMap()), false); int RowNnz; #ifdef IFPACK_FLOPCOUNTERS double flops = 0.0; #endif H_ = Teuchos::rcp(new Epetra_CrsMatrix(Copy,*SerialMap_,0)); if (H_.get() == 0) IFPACK_CHK_ERR(-5); // memory allocation error // get A(0,0) element and insert it (after sqrt) IFPACK_CHK_ERR(A_.ExtractMyRowCopy(0,Length,RowNnz, &RowValues[0],&RowIndices[0])); // skip off-processor elements if (distributed) { int count = 0; for (int i = 0 ;i < RowNnz ; ++i) { if (RowIndices[i] < NumMyRows_){ RowIndices[count] = RowIndices[i]; RowValues[count] = RowValues[i]; ++count; } else continue; } RowNnz = count; } // modify diagonal double diag_val = 0.0; for (int i = 0 ;i < RowNnz ; ++i) { if (RowIndices[i] == 0) { double& v = RowValues[i]; diag_val = AbsoluteThreshold() * EPETRA_SGN(v) + RelativeThreshold() * v; break; } } diag_val = sqrt(diag_val); int diag_idx = 0; EPETRA_CHK_ERR(H_->InsertGlobalValues(0,1,&diag_val, &diag_idx)); // The 10 is just a small constant to limit collisons as the actual keys // we store are the indices and not integers // [0..A_.MaxNumEntries()*LevelofFill()]. Ifpack_HashTable Hash( 10 * A_.MaxNumEntries() * LevelOfFill(), 1); // start factorization for line 1 for (int row_i = 1 ; row_i < NumMyRows_ ; ++row_i) { // get row `row_i' of the matrix IFPACK_CHK_ERR(A_.ExtractMyRowCopy(row_i,Length,RowNnz, &RowValues[0],&RowIndices[0])); // skip off-processor elements if (distributed) { int count = 0; for (int i = 0 ;i < RowNnz ; ++i) { if (RowIndices[i] < NumMyRows_){ RowIndices[count] = RowIndices[i]; RowValues[count] = RowValues[i]; ++count; } else continue; } RowNnz = count; } // number of nonzeros in this row are defined as the nonzeros // of the matrix, plus the level of fill int LOF = (int)(LevelOfFill() * RowNnz); if (LOF == 0) LOF = 1; // convert line `row_i' into hash for fast access Hash.reset(); double h_ii = 0.0; for (int i = 0 ; i < RowNnz ; ++i) { if (RowIndices[i] == row_i) { double& v = RowValues[i]; h_ii = AbsoluteThreshold() * EPETRA_SGN(v) + RelativeThreshold() * v; } else if (RowIndices[i] < row_i) { Hash.set(RowIndices[i], RowValues[i], true); } } // form element (row_i, col_j) // I start from the first row that has a nonzero column // index in row_i. for (int col_j = RowIndices[0] ; col_j < row_i ; ++col_j) { double h_ij = 0.0, h_jj = 0.0; // note: get() returns 0.0 if col_j is not found h_ij = Hash.get(col_j); // get pointers to row `col_j' int* ColIndices; double* ColValues; int ColNnz; H_->ExtractGlobalRowView(col_j, ColNnz, ColValues, ColIndices); for (int k = 0 ; k < ColNnz ; ++k) { int col_k = ColIndices[k]; if (col_k == col_j) h_jj = ColValues[k]; else { double xxx = Hash.get(col_k); if (xxx != 0.0) { h_ij -= ColValues[k] * xxx; #ifdef IFPACK_FLOPCOUNTERS flops += 2.0; #endif } } } h_ij /= h_jj; if (IFPACK_ABS(h_ij) > DropTolerance_) { Hash.set(col_j, h_ij); } #ifdef IFPACK_FLOPCOUNTERS // only approx ComputeFlops_ += 2.0 * flops + 1.0; #endif } int size = Hash.getNumEntries(); vector<double> AbsRow(size); int count = 0; // +1 because I use the extra position for diagonal in insert vector<int> keys(size + 1); vector<double> values(size + 1); Hash.arrayify(&keys[0], &values[0]); for (int i = 0 ; i < size ; ++i) { AbsRow[i] = IFPACK_ABS(values[i]); } count = size; double cutoff = 0.0; if (count > LOF) { nth_element(AbsRow.begin(), AbsRow.begin() + LOF, AbsRow.begin() + count, std::greater<double>()); cutoff = AbsRow[LOF]; } for (int i = 0 ; i < size ; ++i) { h_ii -= values[i] * values[i]; } if (h_ii < 0.0) h_ii = 1e-12;; h_ii = sqrt(h_ii); #ifdef IFPACK_FLOPCOUNTERS // only approx, + 1 == sqrt ComputeFlops_ += 2 * size + 1; #endif double DiscardedElements = 0.0; count = 0; for (int i = 0 ; i < size ; ++i) { if (IFPACK_ABS(values[i]) > cutoff) { values[count] = values[i]; keys[count] = keys[i]; ++count; } else DiscardedElements += values[i]; } if (RelaxValue() != 0.0) { DiscardedElements *= RelaxValue(); h_ii += DiscardedElements; } values[count] = h_ii; keys[count] = row_i; ++count; H_->InsertGlobalValues(row_i, count, &(values[0]), (int*)&(keys[0])); } IFPACK_CHK_ERR(H_->FillComplete()); #if 0 // to check the complete factorization Epetra_Vector LHS(Matrix().RowMatrixRowMap()); Epetra_Vector RHS1(Matrix().RowMatrixRowMap()); Epetra_Vector RHS2(Matrix().RowMatrixRowMap()); Epetra_Vector RHS3(Matrix().RowMatrixRowMap()); LHS.Random(); Matrix().Multiply(false,LHS,RHS1); H_->Multiply(true,LHS,RHS2); H_->Multiply(false,RHS2,RHS3); RHS1.Update(-1.0, RHS3, 1.0); cout << endl; cout << RHS1; #endif int MyNonzeros = H_->NumGlobalNonzeros(); Comm().SumAll(&MyNonzeros, &GlobalNonzeros_, 1); IsComputed_ = true; #ifdef IFPACK_FLOPCOUNTERS double TotalFlops; // sum across all the processors A_.Comm().SumAll(&flops, &TotalFlops, 1); ComputeFlops_ += TotalFlops; #endif ++NumCompute_; ComputeTime_ += Time_.ElapsedTime(); return(0); }
void MeshEnergy::GetKappa( const std::vector<int>& C, const std::vector<double>& phi, std::valarray<double>& kappa) { // kappa: divergence of normal // dy^2 * dxx - 2dxdydxy + dx^2dyy / ( dx^2 + dy^2 )^(3/2) vtkPoints* verts = meshdata->polydata->GetPoints(); for( ::size_t k_ = 0; k_ < C.size(); k_++ )\ { int k = C[k_]; std::vector<double> nhat(3); nhat[0] = meshdata->nx[k]; // these are normal to surface; the nx_ are the contour normals nhat[1] = meshdata->ny[k]; nhat[2] = meshdata->nz[k]; // step 1. create the rotation matrix that orients the current normal as [0,0,1]'. double phiang = atan2( nhat[0], nhat[1] ); std::vector<double> rotate1(9); rotate1[0] = cos(phiang); rotate1[1] = -sin(phiang); rotate1[2] = 0; rotate1[3] = sin(phiang); rotate1[4] = cos(phiang); rotate1[5] = 0; rotate1[6] = 0; rotate1[7] = 0; rotate1[8] = 1.0; std::vector<double> nhat_a(3); pkmult( nhat, rotate1, nhat_a ); double ytilde = nhat_a[1]; double theta = M_PI_2 - atan2(nhat[2],ytilde); std::vector<double> rotate2(9); rotate2[0] = 1.0; rotate2[1] = 0; rotate2[2] = 0; rotate2[3] = 0; rotate2[4] = cos(theta); rotate2[5] = -sin(theta); rotate2[6] = 0; rotate2[7] = sin(theta); rotate2[8] = cos(theta); std::vector<double> nhat_b(3); pkmult( nhat_a, rotate2, nhat_b ); // nhat_b should now be [0 0 1]' double thispt[3]; verts->GetPoint( k, thispt ); // apply rotate2 * rotate1 to each *translated* neighbor of this k-th point ::size_t num_neigh = meshdata->adj[k].myNeighbs.size(); double vec[3]; std::vector<double> vv(3); std::vector<double> vv_(3); std::valarray<double> xdata(num_neigh); std::valarray<double> ydata(num_neigh); std::valarray<double> zdata(num_neigh); // step 2. create temporary set of std::vectors as copies of neighboring points // translated to origin // step 3. apply the rotation to all these points for (::size_t i = 0; i < num_neigh; i++ ) { int idx = meshdata->adj[k].myNeighbs[i]; verts->GetPoint( idx, vec ); vv[0] = vec[0] - thispt[0]; vv[1] = vec[1] - thispt[1]; vv[2] = vec[2] - thispt[2]; pkmult( vv, rotate1, vv_ ); pkmult( vv_, rotate2, vv ); xdata[i] = vv[0]; ydata[i] = vv[1]; zdata[i] = phi[idx] - phi[k]; //vv[2]; // zero reference phi at the vertex where we are forming tangent plane } /*if( abs(zdata).min() < 1e-6 ) continue;*/ // step 4. find first derivatives double phi_x = 0.0; double phi_y = 0.0; { std::valarray<double> RHS(2); std::valarray<double> ATA(4); ATA[0] = (xdata * xdata).sum(); ATA[1] = (xdata * ydata).sum(); ATA[2] = ATA[1]; ATA[3] = (ydata * ydata).sum(); RHS[0] = (xdata * zdata).sum(); RHS[1] = (ydata * zdata).sum(); int maxits = 1000; std::valarray<double> ab = RHS; // initial guess std::valarray<double> LHS(2); pkmult2( ab, ATA, LHS ); double res = sqrt( ( (LHS - RHS)*(LHS - RHS) ).sum() ); double tol = 1e-8; int iter = 0; while( iter < maxits && res > tol ) { iter++; ab[0] = (RHS[0] - ( ab[1]*ATA[1] ) )/ ATA[0]; ab[1] = (RHS[1] - ( ab[0]*ATA[2] ) )/ ATA[3]; pkmult2( ab, ATA, LHS ); res = sqrt( ( (LHS - RHS)*(LHS - RHS) ).sum() ); } phi_x = ab[0]; phi_y = ab[1]; } // step 4. find least-squares fit for phi(x,y) = ax^2 + bxy + cy^2 // to get second derivatives std::valarray<double> RHS(3); // A'z RHS[0] = ( xdata * xdata * zdata ).sum(); RHS[1] = ( xdata * ydata * zdata ).sum(); RHS[2] = ( ydata * ydata * zdata ).sum(); double tik_delta = 1e-1 * abs(RHS).min(); std::vector<double> ATA(9); // A'A ATA[0] = tik_delta + (xdata * xdata * xdata * xdata).sum(); ATA[1] = (xdata * xdata * xdata * ydata).sum(); ATA[2] = (xdata * xdata * ydata * ydata).sum(); ATA[3] = (xdata * ydata * xdata * xdata).sum(); ATA[4] = tik_delta + (xdata * ydata * xdata * ydata).sum(); ATA[5] = (xdata * ydata * ydata * ydata).sum(); ATA[6] = (ydata * ydata * xdata * xdata).sum(); ATA[7] = (ydata * ydata * xdata * ydata).sum(); ATA[8] = tik_delta + (ydata * ydata * ydata * ydata).sum(); int maxits = 1000; std::valarray<double> abc = RHS; // initial guess std::valarray<double> LHS(3); pkmult( abc, ATA, LHS ); double res = sqrt( ( (LHS - RHS)*(LHS - RHS) ).sum() ); double tol = 1e-8; int iter = 0; while( iter < maxits && res > tol ) { iter++; abc[0] = (RHS[0] - ( abc[1]*ATA[1] + abc[2]*ATA[2] ) )/ ATA[0]; abc[1] = (RHS[1] - ( abc[0]*ATA[3] + abc[2]*ATA[5] ) )/ ATA[4]; abc[2] = (RHS[2] - ( abc[0]*ATA[6] + abc[1]*ATA[7] ) )/ ATA[8]; pkmult( abc, ATA, LHS ); res = sqrt( ( (LHS - RHS)*(LHS - RHS) ).sum() ); } // step 5. get the derivatives from quadratic form double phi_xx = 2*abc[0]; double phi_xy = abc[1]; double phi_yy = 2*abc[2]; kappa[k_] = phi_y * phi_y * phi_xx - 2 * phi_x * phi_y * phi_xy + phi_x * phi_x * phi_yy; if( abs(phi_x) + abs(phi_y) > 1e-9 ) { kappa[k_] /= pow( (phi_x*phi_x + phi_y*phi_y), 1.5 ); } } }
int main(int argc, char *argv[]) { // initialize MPI and Epetra communicator #ifdef HAVE_MPI MPI_Init(&argc,&argv); Epetra_MpiComm Comm( MPI_COMM_WORLD ); #else Epetra_SerialComm Comm; #endif Teuchos::ParameterList GaleriList; // The problem is defined on a 2D grid, global size is nx * nx. int nx = 30; GaleriList.set("nx", nx); GaleriList.set("ny", nx * Comm.NumProc()); GaleriList.set("mx", 1); GaleriList.set("my", Comm.NumProc()); Teuchos::RefCountPtr<Epetra_Map> Map = Teuchos::rcp( Galeri::CreateMap("Cartesian2D", Comm, GaleriList) ); Teuchos::RefCountPtr<Epetra_RowMatrix> A = Teuchos::rcp( Galeri::CreateCrsMatrix("Laplace2D", &*Map, GaleriList) ); // =============================================================== // // B E G I N N I N G O F I F P A C K C O N S T R U C T I O N // // =============================================================== // Teuchos::ParameterList List; // allocates an IFPACK factory. No data is associated // to this object (only method Create()). Ifpack Factory; // create the preconditioner. For valid PrecType values, // please check the documentation std::string PrecType = "Amesos"; int OverlapLevel = 2; // must be >= 0. If Comm.NumProc() == 1, // it is ignored. Teuchos::RefCountPtr<Ifpack_Preconditioner> Prec = Teuchos::rcp( Factory.Create(PrecType, &*A, OverlapLevel) ); assert(Prec != Teuchos::null); // specify the Amesos solver to be used. // If the selected solver is not available, // IFPACK will try to use Amesos' KLU (which is usually always // compiled). Amesos' serial solvers are: // "Amesos_Klu", "Amesos_Umfpack", "Amesos_Superlu" List.set("amesos: solver type", "Amesos_Klu"); // sets the parameters IFPACK_CHK_ERR(Prec->SetParameters(List)); // initialize the preconditioner. At this point the matrix must // have been FillComplete()'d, but actual values are ignored. // At this call, Amesos will perform the symbolic factorization. IFPACK_CHK_ERR(Prec->Initialize()); // Builds the preconditioners, by looking for the values of // the matrix. At this call, Amesos will perform the // numeric factorization. IFPACK_CHK_ERR(Prec->Compute()); // =================================================== // // E N D O F I F P A C K C O N S T R U C T I O N // // =================================================== // // At this point, we need some additional objects // to define and solve the linear system. // defines LHS and RHS Epetra_Vector LHS(A->OperatorDomainMap()); Epetra_Vector RHS(A->OperatorDomainMap()); // solution is constant LHS.PutScalar(1.0); // now build corresponding RHS A->Apply(LHS,RHS); // now randomize the solution RHS.Random(); // need an Epetra_LinearProblem to define AztecOO solver Epetra_LinearProblem Problem(&*A,&LHS,&RHS); // now we can allocate the AztecOO solver AztecOO Solver(Problem); // specify solver Solver.SetAztecOption(AZ_solver,AZ_gmres); Solver.SetAztecOption(AZ_output,32); // HERE WE SET THE IFPACK PRECONDITIONER Solver.SetPrecOperator(&*Prec); // .. and here we solve // NOTE: with one process, the solver must converge in // one iteration. Solver.Iterate(1550,1e-8); #ifdef HAVE_MPI MPI_Finalize() ; #endif return(EXIT_SUCCESS); }
void MeshEnergy::GetNormalsTangentPlane( const std::vector<int>& C, const std::vector<double>& phi, std::valarray<double>& ne1, std::valarray<double>& ne2, MeshData* vtkNotUsed(meshdata)) { vtkPoints* verts = meshdata->polydata->GetPoints(); for( ::size_t k_ = 0; k_ < C.size(); k_++ ) { int k = C[k_]; std::vector<double> nhat(3); nhat[0] = meshdata->nx[k]; // these are normal to surface; the nx_ are the contour normals nhat[1] = meshdata->ny[k]; nhat[2] = meshdata->nz[k]; // step 1. create the rotation matrix that orients the current normal as [0,0,1]'. double phiang = atan2( nhat[0], nhat[1] ); std::vector<double> rotate1(9); rotate1[0] = cos(phiang); rotate1[1] = -sin(phiang); rotate1[2] = 0; rotate1[3] = sin(phiang); rotate1[4] = cos(phiang); rotate1[5] = 0; rotate1[6] = 0; rotate1[7] = 0; rotate1[8] = 1.0; std::vector<double> nhat_a(3); pkmult( nhat, rotate1, nhat_a ); double ytilde = nhat_a[1]; double theta = M_PI_2 - atan2(nhat[2],ytilde); std::vector<double> rotate2(9); rotate2[0] = 1.0; rotate2[1] = 0; rotate2[2] = 0; rotate2[3] = 0; rotate2[4] = cos(theta); rotate2[5] = -sin(theta); rotate2[6] = 0; rotate2[7] = sin(theta); rotate2[8] = cos(theta); std::vector<double> nhat_b(3); pkmult( nhat_a, rotate2, nhat_b ); // nhat_b should now be [0 0 1]' double thispt[3]; verts->GetPoint( k, thispt ); // apply rotate2 * rotate1 to each *translated* neighbor of this k-th point ::size_t num_neigh = meshdata->adj[k].myNeighbs.size(); double vec[3]; std::vector<double> vv(3); std::vector<double> vv_(3); std::valarray<double> xdata(num_neigh); std::valarray<double> ydata(num_neigh); std::valarray<double> zdata(num_neigh); // step 2. create temporary set of std::vectors as copies of neighboring points // translated to origin // step 3. apply the rotation to all these points for ( ::size_t i = 0; i < num_neigh; i++ ) { int idx = meshdata->adj[k].myNeighbs[i]; verts->GetPoint( idx, vec ); vv[0] = vec[0] - thispt[0]; vv[1] = vec[1] - thispt[1]; vv[2] = vec[2] - thispt[2]; pkmult( vv, rotate1, vv_ ); pkmult( vv_, rotate2, vv ); xdata[i] = vv[0]; ydata[i] = vv[1]; zdata[i] = phi[idx] - phi[k]; //vv[2]; // zero reference phi at the vertex where we are forming tangent plane } /*if( abs(zdata).min() < 1e-6 ) continue;*/ // step 4. find least-squares fit for H(x,y) = ax + by std::valarray<double> RHS(2); std::valarray<double> ATA(4); ATA[0] = (xdata * xdata).sum(); ATA[1] = (xdata * ydata).sum(); ATA[2] = ATA[1]; ATA[3] = (ydata * ydata).sum(); RHS[0] = (xdata * zdata).sum(); RHS[1] = (ydata * zdata).sum(); int maxits = 1000; std::valarray<double> ab = RHS; // initial guess std::valarray<double> LHS(2); pkmult2( ab, ATA, LHS ); double res = sqrt( ( (LHS - RHS)*(LHS - RHS) ).sum() ); double tol = 1e-8; int iter = 0; while( iter < maxits && res > tol ) { iter++; ab[0] = (RHS[0] - ( ab[1]*ATA[1] ) )/ ATA[0]; ab[1] = (RHS[1] - ( ab[0]*ATA[2] ) )/ ATA[3]; pkmult2( ab, ATA, LHS ); res = sqrt( ( (LHS - RHS)*(LHS - RHS) ).sum() ); } ne1[k_] = ab[0] / sqrt( (ab*ab).sum() ); ne2[k_] = ab[1] / sqrt( (ab*ab).sum() ); // step 5. differentiate the plane along principal directions } }
// ====================================================================== bool ComparePointAndBlock(string PrecType, const Teuchos::RefCountPtr<Epetra_RowMatrix>& A, int sweeps) { Epetra_MultiVector RHS(A->RowMatrixRowMap(), NumVectors); Epetra_MultiVector LHS(A->RowMatrixRowMap(), NumVectors); LHS.PutScalar(0.0); RHS.Random(); Epetra_LinearProblem Problem(&*A, &LHS, &RHS); // Set up the list Teuchos::ParameterList List; List.set("relaxation: damping factor", 1.0); List.set("relaxation: type", PrecType); List.set("relaxation: sweeps",sweeps); List.set("partitioner: type", "linear"); List.set("partitioner: local parts", A->NumMyRows()); int ItersPoint, ItersBlock; // ================================================== // // get the number of iterations with point relaxation // // ================================================== // { RHS.PutScalar(1.0); LHS.PutScalar(0.0); Ifpack_PointRelaxation Point(&*A); Point.SetParameters(List); Point.Compute(); // set AztecOO solver object AztecOO AztecOOSolver(Problem); AztecOOSolver.SetAztecOption(AZ_solver,Solver); if (verbose) AztecOOSolver.SetAztecOption(AZ_output,32); else AztecOOSolver.SetAztecOption(AZ_output,AZ_none); AztecOOSolver.SetPrecOperator(&Point); AztecOOSolver.Iterate(2550,1e-2); double TrueResidual = AztecOOSolver.TrueResidual(); ItersPoint = AztecOOSolver.NumIters(); // some output if (verbose && Problem.GetMatrix()->Comm().MyPID() == 0) { cout << "Iterations = " << ItersPoint << endl; cout << "Norm of the true residual = " << TrueResidual << endl; } } // ================================================== // // get the number of iterations with block relaxation // // ================================================== // { RHS.PutScalar(1.0); LHS.PutScalar(0.0); Ifpack_BlockRelaxation<Ifpack_SparseContainer<Ifpack_Amesos> > Block(&*A); Block.SetParameters(List); Block.Compute(); // set AztecOO solver object AztecOO AztecOOSolver(Problem); AztecOOSolver.SetAztecOption(AZ_solver,Solver); if (verbose) AztecOOSolver.SetAztecOption(AZ_output,32); else AztecOOSolver.SetAztecOption(AZ_output,AZ_none); AztecOOSolver.SetPrecOperator(&Block); AztecOOSolver.Iterate(2550,1e-2); double TrueResidual = AztecOOSolver.TrueResidual(); ItersBlock = AztecOOSolver.NumIters(); // some output if (verbose && Problem.GetMatrix()->Comm().MyPID() == 0) { cout << "Iterations " << ItersBlock << endl; cout << "Norm of the true residual = " << TrueResidual << endl; } } int diff = ItersPoint - ItersBlock; if (diff < 0) diff = -diff; if (diff > 10) { if (verbose) cout << "ComparePointandBlock TEST FAILED!" << endl; return(false); } else { if (verbose) cout << "ComparePointandBlock TEST PASSED" << endl; return(true); } }
int main(int argc, char *argv[]) { int ierr = 0, i, j, k; bool debug = false; #ifdef EPETRA_MPI MPI_Init(&argc,&argv); Epetra_MpiComm Comm( MPI_COMM_WORLD ); #else Epetra_SerialComm Comm; #endif bool verbose = false; // Check if we should print results to standard out if (argc>1) if (argv[1][0]=='-' && argv[1][1]=='v') verbose = true; if (verbose && Comm.MyPID()==0) cout << Epetra_Version() << endl << endl; int rank = Comm.MyPID(); // char tmp; // if (rank==0) cout << "Press any key to continue..."<< endl; // if (rank==0) cin >> tmp; // Comm.Barrier(); Comm.SetTracebackMode(0); // This should shut down any error traceback reporting if (verbose) cout << Comm <<endl; // bool verbose1 = verbose; // Redefine verbose to only print on PE 0 if (verbose && rank!=0) verbose = false; int N = 20; int NRHS = 4; double * A = new double[N*N]; double * A1 = new double[N*N]; double * X = new double[(N+1)*NRHS]; double * X1 = new double[(N+1)*NRHS]; int LDX = N+1; int LDX1 = N+1; double * B = new double[N*NRHS]; double * B1 = new double[N*NRHS]; int LDB = N; int LDB1 = N; int LDA = N; int LDA1 = LDA; double OneNorm1; bool Transpose = false; Epetra_SerialDenseSolver solver; Epetra_SerialDenseMatrix * Matrix; for (int kk=0; kk<2; kk++) { for (i=1; i<=N; i++) { GenerateHilbert(A, LDA, i); OneNorm1 = 0.0; for (j=1; j<=i; j++) OneNorm1 += 1.0/((double) j); // 1-Norm = 1 + 1/2 + ...+1/n if (kk==0) { Matrix = new Epetra_SerialDenseMatrix(View, A, LDA, i, i); LDA1 = LDA; } else { Matrix = new Epetra_SerialDenseMatrix(Copy, A, LDA, i, i); LDA1 = i; } GenerateHilbert(A1, LDA1, i); if (kk==1) { solver.FactorWithEquilibration(true); solver.SolveWithTranspose(true); Transpose = true; solver.SolveToRefinedSolution(true); } for (k=0; k<NRHS; k++) for (j=0; j<i; j++) { B[j+k*LDB] = 1.0/((double) (k+3)*(j+3)); B1[j+k*LDB1] = B[j+k*LDB1]; } Epetra_SerialDenseMatrix Epetra_B(View, B, LDB, i, NRHS); Epetra_SerialDenseMatrix Epetra_X(View, X, LDX, i, NRHS); solver.SetMatrix(*Matrix); solver.SetVectors(Epetra_X, Epetra_B); ierr = check(solver, A1, LDA1, i, NRHS, OneNorm1, B1, LDB1, X1, LDX1, Transpose, verbose); assert (ierr>-1); delete Matrix; if (ierr!=0) { if (verbose) cout << "Factorization failed due to bad conditioning. This is normal if RCOND is small." << endl; break; } } } delete [] A; delete [] A1; delete [] X; delete [] X1; delete [] B; delete [] B1; ///////////////////////////////////////////////////////////////////// // Now test norms and scaling functions ///////////////////////////////////////////////////////////////////// Epetra_SerialDenseMatrix D; double ScalarA = 2.0; int DM = 10; int DN = 8; D.Shape(DM, DN); for (j=0; j<DN; j++) for (i=0; i<DM; i++) D[j][i] = (double) (1+i+j*DM) ; //cout << D << endl; double NormInfD_ref = (double)(DM*(DN*(DN+1))/2); double NormOneD_ref = (double)((DM*DN*(DM*DN+1))/2 - (DM*(DN-1)*(DM*(DN-1)+1))/2 ); double NormInfD = D.NormInf(); double NormOneD = D.NormOne(); if (verbose) { cout << " *** Before scaling *** " << endl << " Computed one-norm of test matrix = " << NormOneD << endl << " Expected one-norm = " << NormOneD_ref << endl << " Computed inf-norm of test matrix = " << NormInfD << endl << " Expected inf-norm = " << NormInfD_ref << endl; } D.Scale(ScalarA); // Scale entire D matrix by this value NormInfD = D.NormInf(); NormOneD = D.NormOne(); if (verbose) { cout << " *** After scaling *** " << endl << " Computed one-norm of test matrix = " << NormOneD << endl << " Expected one-norm = " << NormOneD_ref*ScalarA << endl << " Computed inf-norm of test matrix = " << NormInfD << endl << " Expected inf-norm = " << NormInfD_ref*ScalarA << endl; } ///////////////////////////////////////////////////////////////////// // Now test that A.Multiply(false, x, y) produces the same result // as y.Multiply('N','N', 1.0, A, x, 0.0). ///////////////////////////////////////////////////////////////////// N = 10; int M = 10; LDA = N; Epetra_SerialDenseMatrix smallA(N, M, false); Epetra_SerialDenseMatrix x(N, 1, false); Epetra_SerialDenseMatrix y1(N, 1, false); Epetra_SerialDenseMatrix y2(N, 1, false); for(i=0; i<N; ++i) { for(j=0; j<M; ++j) { smallA(i,j) = 1.0*i+2.0*j+1.0; } x(i,0) = 1.0; y1(i,0) = 0.0; y2(i,0) = 0.0; } //quick check of operator== if (x == y1) { if (verbose) cout << "err in Epetra_SerialDenseMatrix::operator==, " << "erroneously returned true." << std::endl; return(-1); } //quick check of operator!= if (x != x) { if (verbose) cout << "err in Epetra_SerialDenseMatrix::operator==, " << "erroneously returned true." << std::endl; return(-1); } int err1 = smallA.Multiply(false, x, y1); int err2 = y2.Multiply('N','N', 1.0, smallA, x, 0.0); if (err1 != 0 || err2 != 0) { if (verbose) cout << "err in Epetra_SerialDenseMatrix::Multiply"<<endl; return(err1+err2); } for(i=0; i<N; ++i) { if (y1(i,0) != y2(i,0)) { if (verbose) cout << "different versions of Multiply don't match."<<endl; return(-99); } } ///////////////////////////////////////////////////////////////////// // Now test for larger system, both correctness and performance. ///////////////////////////////////////////////////////////////////// N = 2000; NRHS = 5; LDA = N; LDB = N; LDX = N; if (verbose) cout << "\n\nComputing factor of an " << N << " x " << N << " general matrix...Please wait.\n\n" << endl; // Define A and X A = new double[LDA*N]; X = new double[LDB*NRHS]; for (j=0; j<N; j++) { for (k=0; k<NRHS; k++) X[j+k*LDX] = 1.0/((double) (j+5+k)); for (i=0; i<N; i++) { if (i==((j+2)%N)) A[i+j*LDA] = 100.0 + i; else A[i+j*LDA] = -11.0/((double) (i+5)*(j+2)); } } // Define Epetra_SerialDenseMatrix object Epetra_SerialDenseMatrix BigMatrix(Copy, A, LDA, N, N); Epetra_SerialDenseMatrix OrigBigMatrix(View, A, LDA, N, N); Epetra_SerialDenseSolver BigSolver; BigSolver.FactorWithEquilibration(true); BigSolver.SetMatrix(BigMatrix); // Time factorization Epetra_Flops counter; BigSolver.SetFlopCounter(counter); Epetra_Time Timer(Comm); double tstart = Timer.ElapsedTime(); ierr = BigSolver.Factor(); if (ierr!=0 && verbose) cout << "Error in factorization = "<<ierr<< endl; assert(ierr==0); double time = Timer.ElapsedTime() - tstart; double FLOPS = counter.Flops(); double MFLOPS = FLOPS/time/1000000.0; if (verbose) cout << "MFLOPS for Factorization = " << MFLOPS << endl; // Define Left hand side and right hand side Epetra_SerialDenseMatrix LHS(View, X, LDX, N, NRHS); Epetra_SerialDenseMatrix RHS; RHS.Shape(N,NRHS); // Allocate RHS // Compute RHS from A and X Epetra_Flops RHS_counter; RHS.SetFlopCounter(RHS_counter); tstart = Timer.ElapsedTime(); RHS.Multiply('N', 'N', 1.0, OrigBigMatrix, LHS, 0.0); time = Timer.ElapsedTime() - tstart; Epetra_SerialDenseMatrix OrigRHS = RHS; FLOPS = RHS_counter.Flops(); MFLOPS = FLOPS/time/1000000.0; if (verbose) cout << "MFLOPS to build RHS (NRHS = " << NRHS <<") = " << MFLOPS << endl; // Set LHS and RHS and solve BigSolver.SetVectors(LHS, RHS); tstart = Timer.ElapsedTime(); ierr = BigSolver.Solve(); if (ierr==1 && verbose) cout << "LAPACK guidelines suggest this matrix might benefit from equilibration." << endl; else if (ierr!=0 && verbose) cout << "Error in solve = "<<ierr<< endl; assert(ierr>=0); time = Timer.ElapsedTime() - tstart; FLOPS = BigSolver.Flops(); MFLOPS = FLOPS/time/1000000.0; if (verbose) cout << "MFLOPS for Solve (NRHS = " << NRHS <<") = " << MFLOPS << endl; double * resid = new double[NRHS]; bool OK = Residual(N, NRHS, A, LDA, BigSolver.Transpose(), BigSolver.X(), BigSolver.LDX(), OrigRHS.A(), OrigRHS.LDA(), resid); if (verbose) { if (!OK) cout << "************* Residual do not meet tolerance *************" << endl; for (i=0; i<NRHS; i++) cout << "Residual[" << i <<"] = "<< resid[i] << endl; cout << endl; } // Solve again using the Epetra_SerialDenseVector class for LHS and RHS Epetra_SerialDenseVector X2; Epetra_SerialDenseVector B2; X2.Size(BigMatrix.N()); B2.Size(BigMatrix.M()); int length = BigMatrix.N(); {for (int kk=0; kk<length; kk++) X2[kk] = ((double ) kk)/ ((double) length);} // Define entries of X2 RHS_counter.ResetFlops(); B2.SetFlopCounter(RHS_counter); tstart = Timer.ElapsedTime(); B2.Multiply('N', 'N', 1.0, OrigBigMatrix, X2, 0.0); // Define B2 = A*X2 time = Timer.ElapsedTime() - tstart; Epetra_SerialDenseVector OrigB2 = B2; FLOPS = RHS_counter.Flops(); MFLOPS = FLOPS/time/1000000.0; if (verbose) cout << "MFLOPS to build single RHS = " << MFLOPS << endl; // Set LHS and RHS and solve BigSolver.SetVectors(X2, B2); tstart = Timer.ElapsedTime(); ierr = BigSolver.Solve(); time = Timer.ElapsedTime() - tstart; if (ierr==1 && verbose) cout << "LAPACK guidelines suggest this matrix might benefit from equilibration." << endl; else if (ierr!=0 && verbose) cout << "Error in solve = "<<ierr<< endl; assert(ierr>=0); FLOPS = counter.Flops(); MFLOPS = FLOPS/time/1000000.0; if (verbose) cout << "MFLOPS to solve single RHS = " << MFLOPS << endl; OK = Residual(N, 1, A, LDA, BigSolver.Transpose(), BigSolver.X(), BigSolver.LDX(), OrigB2.A(), OrigB2.LDA(), resid); if (verbose) { if (!OK) cout << "************* Residual do not meet tolerance *************" << endl; cout << "Residual = "<< resid[0] << endl; } delete [] resid; delete [] A; delete [] X; /////////////////////////////////////////////////// // Now test default constructor and index operators /////////////////////////////////////////////////// N = 5; Epetra_SerialDenseMatrix C; // Implicit call to default constructor, should not need to call destructor C.Shape(5,5); // Make it 5 by 5 double * C1 = new double[N*N]; GenerateHilbert(C1, N, N); // Generate Hilber matrix C1[1+2*N] = 1000.0; // Make matrix nonsymmetric // Fill values of C with Hilbert values for (i=0; i<N; i++) for (j=0; j<N; j++) C(i,j) = C1[i+j*N]; // Test if values are correctly written and read for (i=0; i<N; i++) for (j=0; j<N; j++) { assert(C(i,j) == C1[i+j*N]); assert(C(i,j) == C[j][i]); } if (verbose) cout << "Default constructor and index operator check OK. Values of Hilbert matrix = " << endl << C << endl << "Values should be 1/(i+j+1), except value (1,2) should be 1000" << endl; delete [] C1; // now test sized/shaped constructor Epetra_SerialDenseMatrix shapedMatrix(10, 12); assert(shapedMatrix.M() == 10); assert(shapedMatrix.N() == 12); for(i = 0; i < 10; i++) for(j = 0; j < 12; j++) assert(shapedMatrix(i, j) == 0.0); Epetra_SerialDenseVector sizedVector(20); assert(sizedVector.Length() == 20); for(i = 0; i < 20; i++) assert(sizedVector(i) == 0.0); if (verbose) cout << "Shaped/sized constructors check OK." << endl; // test Copy/View mode in op= and cpy ctr int temperr = 0; temperr = matrixAssignment(verbose, debug); if(verbose && temperr == 0) cout << "Operator = checked OK." << endl; EPETRA_TEST_ERR(temperr, ierr); temperr = matrixCpyCtr(verbose, debug); if(verbose && temperr == 0) cout << "Copy ctr checked OK." << endl; EPETRA_TEST_ERR(temperr, ierr); // Test some vector methods Epetra_SerialDenseVector v1(3); v1[0] = 1.0; v1[1] = 3.0; v1[2] = 2.0; Epetra_SerialDenseVector v2(3); v2[0] = 2.0; v2[1] = 1.0; v2[2] = -2.0; temperr = 0; if (v1.Norm1()!=6.0) temperr++; if (fabs(sqrt(14.0)-v1.Norm2())>1.0e-6) temperr++; if (v1.NormInf()!=3.0) temperr++; if(verbose && temperr == 0) cout << "Vector Norms checked OK." << endl; temperr = 0; if (v1.Dot(v2)!=1.0) temperr++; if(verbose && temperr == 0) cout << "Vector Dot product checked OK." << endl; #ifdef EPETRA_MPI MPI_Finalize() ; #endif /* end main */ return ierr ; }
double Ifpack_Condest(const Ifpack_Preconditioner& IFP, const Ifpack_CondestType CT, const int MaxIters, const double Tol, Epetra_RowMatrix* Matrix) { double ConditionNumberEstimate = -1.0; if (CT == Ifpack_Cheap) { // Create a vector with all values equal to one Epetra_Vector Ones(IFP.OperatorDomainMap()); Ones.PutScalar(1.0); // Create the vector of results Epetra_Vector OnesResult(IFP.OperatorRangeMap()); // Compute the effect of the solve on the vector of ones IFPACK_CHK_ERR(IFP.ApplyInverse(Ones, OnesResult)); // Make all values non-negative IFPACK_CHK_ERR(OnesResult.Abs(OnesResult)); // Get the maximum value across all processors IFPACK_CHK_ERR(OnesResult.MaxValue(&ConditionNumberEstimate)); } else if (CT == Ifpack_CG) { #ifdef HAVE_IFPACK_AZTECOO if (Matrix == 0) Matrix = (Epetra_RowMatrix*)&(IFP.Matrix()); Epetra_Vector LHS(IFP.OperatorDomainMap()); LHS.PutScalar(0.0); Epetra_Vector RHS(IFP.OperatorRangeMap()); RHS.Random(); Epetra_LinearProblem Problem; Problem.SetOperator(Matrix); Problem.SetLHS(&LHS); Problem.SetRHS(&RHS); AztecOO Solver(Problem); Solver.SetAztecOption(AZ_output,AZ_none); Solver.SetAztecOption(AZ_solver,AZ_cg_condnum); Solver.Iterate(MaxIters,Tol); const double* status = Solver.GetAztecStatus(); ConditionNumberEstimate = status[AZ_condnum]; #endif } else if (CT == Ifpack_GMRES) { #ifdef HAVE_IFPACK_AZTECOO if (Matrix == 0) Matrix = (Epetra_RowMatrix*)&(IFP.Matrix()); Epetra_Vector LHS(IFP.OperatorDomainMap()); LHS.PutScalar(0.0); Epetra_Vector RHS(IFP.OperatorRangeMap()); RHS.Random(); Epetra_LinearProblem Problem; Problem.SetOperator(Matrix); Problem.SetLHS(&LHS); Problem.SetRHS(&RHS); AztecOO Solver(Problem); Solver.SetAztecOption(AZ_solver,AZ_gmres_condnum); Solver.SetAztecOption(AZ_output,AZ_none); // the following can be problematic for large problems, // but any restart would destroy useful information about // the condition number. Solver.SetAztecOption(AZ_kspace,MaxIters); Solver.Iterate(MaxIters,Tol); const double* status = Solver.GetAztecStatus(); ConditionNumberEstimate = status[AZ_condnum]; #endif } return(ConditionNumberEstimate); }
vector<T> matrix<T>::solve(vector<T> RHS) { #ifdef _DEBUG if (this->dims[0] != this->dims[1]) FatalErrorST("Can only use Gaussian elimination on a square matrix."); #endif // Gaussian elimination with full pivoting // not to be used where speed is paramount vector<T> vec(this->dims[0]); vector<T> solution(this->dims[0]); vector<int> swap_0(this->dims[0],1); vector<int> swap_1(this->dims[0],1); vector<T> tmpRow(this->dims[0]); matrix<T> LHS(*this); // setup swap arrays for(uint i=0; i<this->dims[0]; i++) { swap_0[i]=i; swap_1[i]=i; } // make triangular for(uint k=0; k<this->dims[0]-1; k++) { T max = 0; T mag; // find pivot int pivot_i = 0; int pivot_j = 0; for(uint i=k; i<this->dims[0]; i++) { for(uint j=k; j<this->dims[0]; j++) { mag = LHS(i,j)*LHS(i,j); if(mag>max) { pivot_i = i; pivot_j = j; max = mag; } } } // swap the swap arrays int itemp_0 = swap_0[k]; swap_0[k] = swap_0[pivot_i]; swap_0[pivot_i] = itemp_0; itemp_0 = swap_1[k]; swap_1[k] = swap_1[pivot_j]; swap_1[pivot_j] = itemp_0; // swap the columns for(uint i=0; i<this->dims[0]; i++) { tmpRow[i] = LHS(i,pivot_j); LHS(i,pivot_j) = LHS(i,k); LHS(i,k) = tmpRow[i]; } // swap the rows for(uint j=0; j<this->dims[0]; j++) { tmpRow[j] = LHS(pivot_i,j); LHS(pivot_i,j) = LHS(k,j); LHS(k,j) = tmpRow[j]; } T tmp = RHS[pivot_i]; RHS[pivot_i] = RHS[k]; RHS[k] = tmp; // subtraction for(uint i=k+1; i<this->dims[0]; i++) { T first = LHS(i,k); RHS[i] = RHS[i] - first/LHS(k,k)*RHS[k]; for(uint j=k; j<this->dims[0]; j++) LHS(i,j) = LHS(i,j) - (first/LHS(k,k))*LHS(k,j); } // exact zero for(uint j=0; j<k+1; j++) { for(uint i=j+1; i<this->dims[0]; i++) { LHS(i,j)=0.0; } } } // back substitute for(int i=(int)this->dims[0]-1; i>=0; i--) { T dtemp_0 = 0.0; for(uint k = i+1; k<this->dims[0]; k++) { dtemp_0 = dtemp_0 + (LHS(i,k)*vec[k]); } vec[i] = (RHS[i]-dtemp_0)/LHS(i,i); } // swap solution rows for(uint i=0; i<this->dims[0]; i++) solution[swap_1[i]] = vec[i]; return solution; }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI MPI_Init(&argc,&argv); Epetra_MpiComm Comm( MPI_COMM_WORLD ); #else Epetra_SerialComm Comm; #endif Teuchos::ParameterList GaleriList; // The problem is defined on a 2D grid, global size is nx * nx. int nx = 30; GaleriList.set("n", nx * nx); GaleriList.set("nx", nx); GaleriList.set("ny", nx); Teuchos::RefCountPtr<Epetra_Map> Map = Teuchos::rcp( Galeri::CreateMap64("Linear", Comm, GaleriList) ); Teuchos::RefCountPtr<Epetra_RowMatrix> A = Teuchos::rcp( Galeri::CreateCrsMatrix("Laplace2D", &*Map, GaleriList) ); // =============================================================== // // B E G I N N I N G O F I F P A C K C O N S T R U C T I O N // // =============================================================== // Teuchos::ParameterList List; // allocates an IFPACK factory. No data is associated // to this object (only method Create()). Ifpack Factory; // create the preconditioner. For valid PrecType values, // please check the documentation string PrecType = "ILU"; // incomplete LU int OverlapLevel = 1; // must be >= 0. If Comm.NumProc() == 1, // it is ignored. Teuchos::RefCountPtr<Ifpack_Preconditioner> Prec = Teuchos::rcp( Factory.Create(PrecType, &*A, OverlapLevel) ); assert(Prec != Teuchos::null); // specify parameters for ILU List.set("fact: drop tolerance", 1e-9); List.set("fact: level-of-fill", 1); // the combine mode is on the following: // "Add", "Zero", "Insert", "InsertAdd", "Average", "AbsMax" // Their meaning is as defined in file Epetra_CombineMode.h List.set("schwarz: combine mode", "Add"); // sets the parameters IFPACK_CHK_ERR(Prec->SetParameters(List)); // initialize the preconditioner. At this point the matrix must // have been FillComplete()'d, but actual values are ignored. IFPACK_CHK_ERR(Prec->Initialize()); // Builds the preconditioners, by looking for the values of // the matrix. IFPACK_CHK_ERR(Prec->Compute()); // =================================================== // // E N D O F I F P A C K C O N S T R U C T I O N // // =================================================== // // At this point, we need some additional objects // to define and solve the linear system. // defines LHS and RHS Epetra_Vector LHS(A->OperatorDomainMap()); Epetra_Vector RHS(A->OperatorDomainMap()); // solution is constant LHS.PutScalar(1.0); // now build corresponding RHS A->Apply(LHS,RHS); // now randomize the solution RHS.Random(); // need an Epetra_LinearProblem to define AztecOO solver Epetra_LinearProblem Problem(&*A,&LHS,&RHS); // now we can allocate the AztecOO solver AztecOO Solver(Problem); // specify solver Solver.SetAztecOption(AZ_solver,AZ_gmres); Solver.SetAztecOption(AZ_output,32); // HERE WE SET THE IFPACK PRECONDITIONER Solver.SetPrecOperator(&*Prec); // .. and here we solve Solver.Iterate(1550,1e-8); cout << *Prec; #ifdef HAVE_MPI MPI_Finalize() ; #endif return(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { int Nnodes=32*32; /* Total number of nodes in the problem.*/ /* 'Nnodes' must be a perfect square. */ struct user_partition Edge_Partition = {NULL, NULL,0,0,NULL,0,0,0}, Node_Partition = {NULL, NULL,0,0,NULL,0,0,0}; int proc_config[AZ_PROC_SIZE]; #ifdef ML_MPI MPI_Init(&argc,&argv); #endif AZ_set_proc_config(proc_config, COMMUNICATOR); ML_Comm* comm; ML_Comm_Create(&comm); Node_Partition.Nglobal = Nnodes; Edge_Partition.Nglobal = Node_Partition.Nglobal*2; user_partition_nodes(&Node_Partition); user_partition_edges(&Edge_Partition, &Node_Partition); AZ_MATRIX * AZ_Ke = user_Ke_build(&Edge_Partition); AZ_MATRIX * AZ_Kn = user_Kn_build(&Node_Partition); // convert (put wrappers) from Aztec matrices to ML_Operator's ML_Operator * ML_Ke, * ML_Kn, * ML_Tmat; ML_Ke = ML_Operator_Create( comm ); ML_Kn = ML_Operator_Create( comm ); AZ_convert_aztec_matrix_2ml_matrix(AZ_Ke,ML_Ke,proc_config); AZ_convert_aztec_matrix_2ml_matrix(AZ_Kn,ML_Kn,proc_config); ML_Tmat = user_T_build(&Edge_Partition, &Node_Partition, ML_Kn, comm); Epetra_CrsMatrix * Epetra_Kn, * Epetra_Ke, * Epetra_T; int MaxNumNonzeros; double CPUTime; ML_Operator2EpetraCrsMatrix(ML_Ke,Epetra_Ke, MaxNumNonzeros, true,CPUTime); ML_Operator2EpetraCrsMatrix(ML_Kn, Epetra_Kn,MaxNumNonzeros, true,CPUTime); ML_Operator2EpetraCrsMatrix(ML_Tmat,Epetra_T,MaxNumNonzeros, true,CPUTime); Teuchos::ParameterList MLList; ML_Epetra::SetDefaults("maxwell", MLList); MLList.set("ML output", 0); MLList.set("aggregation: type", "Uncoupled"); MLList.set("coarse: max size", 30); MLList.set("aggregation: threshold", 0.0); MLList.set("coarse: type", "Amesos-KLU"); ML_Epetra::MultiLevelPreconditioner * MLPrec = new ML_Epetra::MultiLevelPreconditioner(*Epetra_Ke, *Epetra_T, *Epetra_Kn, MLList); Epetra_Vector LHS(Epetra_Ke->DomainMap()); LHS.Random(); Epetra_Vector RHS(Epetra_Ke->DomainMap()); RHS.PutScalar(1.0); Epetra_LinearProblem Problem(Epetra_Ke,&LHS,&RHS); AztecOO solver(Problem); solver.SetPrecOperator(MLPrec); solver.SetAztecOption(AZ_solver, AZ_cg_condnum); solver.SetAztecOption(AZ_output, 32); solver.Iterate(500, 1e-8); // ========================= // // compute the real residual // // ========================= // Epetra_Vector RHScomp(Epetra_Ke->DomainMap()); int ierr; ierr = Epetra_Ke->Multiply(false, LHS, RHScomp); assert(ierr==0); Epetra_Vector resid(Epetra_Ke->DomainMap()); ierr = resid.Update(1.0, RHS, -1.0, RHScomp, 0.0); assert(ierr==0); double residual; ierr = resid.Norm2(&residual); assert(ierr==0); if (proc_config[AZ_node] == 0) { std::cout << std::endl; std::cout << "==> Residual = " << residual << std::endl; std::cout << std::endl; } // =============== // // C L E A N U P // // =============== // delete MLPrec; // destroy phase prints out some information delete Epetra_Kn; delete Epetra_Ke; delete Epetra_T; ML_Operator_Destroy( &ML_Ke ); ML_Operator_Destroy( &ML_Kn ); ML_Comm_Destroy( &comm ); if (Edge_Partition.my_local_ids != NULL) free(Edge_Partition.my_local_ids); if (Node_Partition.my_local_ids != NULL) free(Node_Partition.my_local_ids); if (Node_Partition.my_global_ids != NULL) free(Node_Partition.my_global_ids); if (Edge_Partition.my_global_ids != NULL) free(Edge_Partition.my_global_ids); if (Node_Partition.needed_external_ids != NULL) free(Node_Partition.needed_external_ids); if (Edge_Partition.needed_external_ids != NULL) free(Edge_Partition.needed_external_ids); if (AZ_Ke!= NULL) { AZ_free(AZ_Ke->bindx); AZ_free(AZ_Ke->val); AZ_free(AZ_Ke->data_org); AZ_matrix_destroy(&AZ_Ke); } if (AZ_Kn!= NULL) { AZ_free(AZ_Kn->bindx); AZ_free(AZ_Kn->val); AZ_free(AZ_Kn->data_org); AZ_matrix_destroy(&AZ_Kn); } ML_Operator_Destroy(&ML_Tmat); if (residual > 1e-5) { std::cout << "`MultiLevelPreconditioner_Maxwell.exe' failed!" << std::endl; exit(EXIT_FAILURE); } #ifdef ML_MPI MPI_Finalize(); #endif if (proc_config[AZ_node] == 0) std::cout << "`MultiLevelPreconditioner_Maxwell.exe' passed!" << std::endl; exit(EXIT_SUCCESS); }