// ============================================================================ void Solve(const Epetra_RowMatrix* Matrix, const Epetra_MultiVector* LHS, const Epetra_MultiVector* RHS) { if (Matrix->Comm().NumProc() != 1) throw(Exception(__FILE__, __LINE__, "Solve() works only in serial")); if (LHS->NumVectors() != RHS->NumVectors()) throw(Exception(__FILE__, __LINE__, "number of vectors in multivectors not consistent")); if(Matrix->NumGlobalRows64() > std::numeric_limits<int>::max()) throw(Exception(__FILE__, __LINE__, "Matrix->NumGlobalRows64() > std::numeric_limits<int>::max()")); int n = static_cast<int>(Matrix->NumGlobalRows64()); int NumVectors = LHS->NumVectors(); Epetra_SerialDenseMatrix DenseMatrix; DenseMatrix.Shape(n, n); for (int i = 0 ; i < n ; ++i) for (int j = 0 ; j < n ; ++j) DenseMatrix(i,j) = 0.0; // allocate storage to extract matrix rows. int Length = Matrix->MaxNumEntries(); vector<double> Values(Length); vector<int> Indices(Length); for (int j = 0 ; j < Matrix->NumMyRows() ; ++j) { int NumEntries; int ierr = Matrix->ExtractMyRowCopy(j, Length, NumEntries, &Values[0], &Indices[0]); for (int k = 0 ; k < NumEntries ; ++k) DenseMatrix(j,Indices[k]) = Values[k]; } Epetra_SerialDenseMatrix DenseX(n, NumVectors); Epetra_SerialDenseMatrix DenseB(n, NumVectors); for (int i = 0 ; i < n ; ++i) for (int j = 0 ; j < NumVectors ; ++j) DenseB(i,j) = (*RHS)[j][i]; Epetra_SerialDenseSolver DenseSolver; DenseSolver.SetMatrix(DenseMatrix); DenseSolver.SetVectors(DenseX,DenseB); DenseSolver.Factor(); DenseSolver.Solve(); for (int i = 0 ; i < n ; ++i) for (int j = 0 ; j < NumVectors ; ++j) (*LHS)[j][i] = DenseX(i,j); }
void FEMLaplaceAssembler::visit(Brick8 *el) { Epetra_SerialDenseMatrix Kloc(8, 8); int numOfGP = 8; GaussPoint** gP = Brick::getGaussPoints(numOfGP); for (int i = 0; i < numOfGP; i++) { std::vector<Epetra_SerialDenseMatrix> basis = Brick::getGaussBasis(8, gP[i]); Epetra_SerialDenseMatrix J = el->getJacobian(basis[1]); Epetra_SerialDenseMatrix TempJ(J); Epetra_SerialDenseSolver JSolver; JSolver.SetMatrix(TempJ); JSolver.Factor(); double detJ = 1; for (int j = 0; j < TempJ.RowDim(); j++) { detJ *= TempJ(j, j); } detJ = fabs(detJ); JSolver.SetMatrix(J); JSolver.Invert(); Epetra_SerialDenseMatrix B(3, 8); Epetra_SerialDenseMatrix BtS(8, 3); B.Multiply('N', 'T', 1, J, basis[1], 0); BtS.Multiply('T', 'N', 1, B, *(el->getInfo()->getMaterial()->getC()), 0); Kloc.Multiply('N', 'N', detJ * gP[i]->getWeigth(), BtS, B, 1); } Epetra_IntSerialDenseVector indexes(8); for (int i = 0; i < 8; i++) indexes(i) = dofMap[el->getPoint(i)][0]; K->SumIntoGlobalValues(indexes, indexes, Kloc); }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI MPI_Init(&argc, &argv); Epetra_MpiComm Comm(MPI_COMM_WORLD); #else Epetra_SerialComm Comm; #endif // Total number of elements in vectors, can be any positive number int NumRows = 5; Epetra_SerialDenseVector x, b; x.Size( NumRows ); b.Size( NumRows ); // set the elements of the vector for( int i=0 ; i<NumRows ; ++i ) b[i] = 1.0, x[i]=0.0; Epetra_SerialDenseMatrix A, A2; A.Shape( NumRows, NumRows ); A2.Shape( NumRows, NumRows ); // A2 is a copy of A // Hilbert matrix (ill-conditioned) for( int i=0 ; i<NumRows ; ++i ) for( int j=0 ; j<NumRows ; ++j ) A(i,j) = 1.0/(i+j+2); cout<< A; // set up the solver Epetra_SerialDenseSolver Problem; Problem.SetMatrix( A ); Problem.SetVectors( x, b ); A2 = A; // we make a copy of A because Problem.Solve() will // overwrite A with its LU decomposition. Try with // cout << A after the following invocation b.Multiply('N','N',1.0, A2, x, 0.0); cout << "A * x = \n" << b; double rcond; Problem.ReciprocalConditionEstimate(rcond); cout << "The (estimated) condition number of A is " << 1/rcond << endl; Problem.SetMatrix( A2 ); Problem.Invert(); cout << "The inverse of A is\n"; cout << A2; #ifdef HAVE_MPI MPI_Finalize(); #endif } /* main */
void FEMLaplaceAssembler::visit(Triangle3 *t) { //cout << force->getValue(t->getCenter()) << endl; Epetra_SerialDenseMatrix R(2, 2); R(0, 0) = t->getPoint(0)->getCoord(0) - t->getPoint(1)->getCoord(0); R(1, 0) = t->getPoint(0)->getCoord(1) - t->getPoint(1)->getCoord(1); R(0, 1) = t->getPoint(2)->getCoord(0) - t->getPoint(0)->getCoord(0); R(1, 1) = t->getPoint(2)->getCoord(1) - t->getPoint(0)->getCoord(1); double detR = R(0, 0) * R(1, 1) - R(1, 0) * R(0, 1); Epetra_SerialDenseSolver RSolv; RSolv.SetMatrix(R); RSolv.Invert(); Epetra_SerialDenseMatrix maper(2, 3); maper(0, 0) = -1; maper(0, 1) = 1; maper(1, 0) = -1; maper(1, 2) = 1; Epetra_SerialDenseMatrix B(2, 3); B.Multiply('T', 'N', 1, R, maper, 0); Epetra_SerialDenseMatrix Kloc(3, 3); Kloc.Multiply('T', 'N', fabs(detR) / 2, B, B, 0); Epetra_IntSerialDenseVector indexes(3); for (int i = 0; i < 3; i++) indexes(i) = dofMap[t->getPoint(i)][0]; K->SumIntoGlobalValues(indexes, indexes, Kloc); }
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 ; }
int check(Epetra_SerialDenseSolver &solver, double * A1, int LDA1, int N1, int NRHS1, double OneNorm1, double * B1, int LDB1, double * X1, int LDX1, bool Transpose, bool verbose) { int i; bool OK; // Test query functions int M= solver.M(); if (verbose) cout << "\n\nNumber of Rows = " << M << endl<< endl; assert(M==N1); int N= solver.N(); if (verbose) cout << "\n\nNumber of Equations = " << N << endl<< endl; assert(N==N1); int LDA = solver.LDA(); if (verbose) cout << "\n\nLDA = " << LDA << endl<< endl; assert(LDA==LDA1); int LDB = solver.LDB(); if (verbose) cout << "\n\nLDB = " << LDB << endl<< endl; assert(LDB==LDB1); int LDX = solver.LDX(); if (verbose) cout << "\n\nLDX = " << LDX << endl<< endl; assert(LDX==LDX1); int NRHS = solver.NRHS(); if (verbose) cout << "\n\nNRHS = " << NRHS << endl<< endl; assert(NRHS==NRHS1); assert(solver.ANORM()==-1.0); assert(solver.RCOND()==-1.0); if (!solver.A_Equilibrated() && !solver.B_Equilibrated()) { assert(solver.ROWCND()==-1.0); assert(solver.COLCND()==-1.0); assert(solver.AMAX()==-1.0); } // Other binary tests assert(!solver.Factored()); assert(solver.Transpose()==Transpose); assert(!solver.SolutionErrorsEstimated()); assert(!solver.Inverted()); assert(!solver.ReciprocalConditionEstimated()); assert(!solver.Solved()); assert(!solver.SolutionRefined()); int ierr = solver.Factor(); assert(ierr>-1); if (ierr!=0) return(ierr); // Factorization failed due to poor conditioning. double rcond; ierr = solver.ReciprocalConditionEstimate(rcond); assert(ierr==0); if (verbose) { double rcond1 = 1.0/exp(3.5*((double)N)); if (N==1) rcond1 = 1.0; cout << "\n\nRCOND = "<< rcond << " should be approx = " << rcond1 << endl << endl; } ierr = solver.Solve(); assert(ierr>-1); if (ierr!=0 && verbose) cout << "LAPACK rules suggest system should be equilibrated." << endl; assert(solver.Factored()); assert(solver.Transpose()==Transpose); assert(solver.ReciprocalConditionEstimated()); assert(solver.Solved()); if (solver.SolutionErrorsEstimated()) { if (verbose) { cout << "\n\nFERR[0] = "<< solver.FERR()[0] << endl; cout << "\n\nBERR[0] = "<< solver.BERR()[0] << endl<< endl; } } double * resid = new double[NRHS]; OK = Residual(N, NRHS, A1, LDA1, solver.Transpose(), solver.X(), solver.LDX(), B1, LDB1, resid); if (verbose) { if (!OK) cout << "************* Residual do not meet tolerance *************" << endl; /* if (solver.A_Equilibrated()) { double * R = solver.R(); double * C = solver.C(); for (i=0; i<solver.M(); i++) cout << "R[" << i <<"] = "<< R[i] << endl; for (i=0; i<solver.N(); i++) cout << "C[" << i <<"] = "<< C[i] << endl; } */ cout << "\n\nResiduals using factorization to solve" << endl; for (i=0; i<NRHS; i++) cout << "Residual[" << i <<"] = "<< resid[i] << endl; cout << endl; } ierr = solver.Invert(); assert(ierr>-1); assert(solver.Inverted()); assert(!solver.Factored()); assert(solver.Transpose()==Transpose); Epetra_SerialDenseMatrix RHS1(Copy, B1, LDB1, N, NRHS); Epetra_SerialDenseMatrix LHS1(Copy, X1, LDX1, N, NRHS); assert(solver.SetVectors(LHS1, RHS1)==0); assert(!solver.Solved()); assert(solver.Solve()>-1); OK = Residual(N, NRHS, A1, LDA1, solver.Transpose(), solver.X(), solver.LDX(), B1, LDB1, resid); if (verbose) { if (!OK) cout << "************* Residual do not meet tolerance *************" << endl; cout << "Residuals using inverse to solve" << endl; for (i=0; i<NRHS; i++) cout << "Residual[" << i <<"] = "<< resid[i] << endl; cout << endl; } delete [] resid; return(0); }
void Projector::projectFunctionOntoBasis(FieldContainer<double> &basisCoefficients, FunctionPtr fxn, BasisPtr basis, BasisCachePtr basisCache, IPPtr ip, VarPtr v, set<int> fieldIndicesToSkip) { CellTopoPtr cellTopo = basis->domainTopology(); DofOrderingPtr dofOrderPtr = Teuchos::rcp(new DofOrdering()); if (! fxn.get()) { TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "fxn cannot be null!"); } int cardinality = basis->getCardinality(); int numCells = basisCache->getPhysicalCubaturePoints().dimension(0); int numDofs = cardinality - fieldIndicesToSkip.size(); if (numDofs==0) { // we're skipping all the fields, so just initialize basisCoefficients to 0 and return basisCoefficients.resize(numCells,cardinality); basisCoefficients.initialize(0); return; } FieldContainer<double> gramMatrix(numCells,cardinality,cardinality); FieldContainer<double> ipVector(numCells,cardinality); // fake a DofOrdering DofOrderingPtr dofOrdering = Teuchos::rcp( new DofOrdering ); if (! basisCache->isSideCache()) { dofOrdering->addEntry(v->ID(), basis, v->rank()); } else { dofOrdering->addEntry(v->ID(), basis, v->rank(), basisCache->getSideIndex()); } ip->computeInnerProductMatrix(gramMatrix, dofOrdering, basisCache); ip->computeInnerProductVector(ipVector, v, fxn, dofOrdering, basisCache); // cout << "physical points for projection:\n" << basisCache->getPhysicalCubaturePoints(); // cout << "gramMatrix:\n" << gramMatrix; // cout << "ipVector:\n" << ipVector; map<int,int> oldToNewIndices; if (fieldIndicesToSkip.size() > 0) { // the code to do with fieldIndicesToSkip might not be terribly efficient... // (but it's not likely to be called too frequently) int i_indices_skipped = 0; for (int i=0; i<cardinality; i++) { int new_index; if (fieldIndicesToSkip.find(i) != fieldIndicesToSkip.end()) { i_indices_skipped++; new_index = -1; } else { new_index = i - i_indices_skipped; } oldToNewIndices[i] = new_index; } FieldContainer<double> gramMatrixFiltered(numCells,numDofs,numDofs); FieldContainer<double> ipVectorFiltered(numCells,numDofs); // now filter out the values that we're to skip for (int cellIndex=0; cellIndex<numCells; cellIndex++) { for (int i=0; i<cardinality; i++) { int i_filtered = oldToNewIndices[i]; if (i_filtered == -1) { continue; } ipVectorFiltered(cellIndex,i_filtered) = ipVector(cellIndex,i); for (int j=0; j<cardinality; j++) { int j_filtered = oldToNewIndices[j]; if (j_filtered == -1) { continue; } gramMatrixFiltered(cellIndex,i_filtered,j_filtered) = gramMatrix(cellIndex,i,j); } } } // cout << "gramMatrixFiltered:\n" << gramMatrixFiltered; // cout << "ipVectorFiltered:\n" << ipVectorFiltered; gramMatrix = gramMatrixFiltered; ipVector = ipVectorFiltered; } for (int cellIndex=0; cellIndex<numCells; cellIndex++){ // TODO: rewrite to take advantage of SerialDenseWrapper... Epetra_SerialDenseSolver solver; Epetra_SerialDenseMatrix A(Copy, &gramMatrix(cellIndex,0,0), gramMatrix.dimension(2), gramMatrix.dimension(2), gramMatrix.dimension(1)); // stride -- fc stores in row-major order (a.o.t. SDM) Epetra_SerialDenseVector b(Copy, &ipVector(cellIndex,0), ipVector.dimension(1)); Epetra_SerialDenseVector x(gramMatrix.dimension(1)); solver.SetMatrix(A); int info = solver.SetVectors(x,b); if (info!=0){ cout << "projectFunctionOntoBasis: failed to SetVectors with error " << info << endl; } bool equilibrated = false; if (solver.ShouldEquilibrate()){ solver.EquilibrateMatrix(); solver.EquilibrateRHS(); equilibrated = true; } info = solver.Solve(); if (info!=0){ cout << "projectFunctionOntoBasis: failed to solve with error " << info << endl; } if (equilibrated) { int successLocal = solver.UnequilibrateLHS(); if (successLocal != 0) { cout << "projection: unequilibration FAILED with error: " << successLocal << endl; } } basisCoefficients.resize(numCells,cardinality); for (int i=0;i<cardinality;i++) { if (fieldIndicesToSkip.size()==0) { basisCoefficients(cellIndex,i) = x(i); } else { int i_filtered = oldToNewIndices[i]; if (i_filtered==-1) { basisCoefficients(cellIndex,i) = 0.0; } else { basisCoefficients(cellIndex,i) = x(i_filtered); } } } } }
void Projector::projectFunctionOntoBasis(FieldContainer<double> &basisCoefficients, Teuchos::RCP<AbstractFunction> fxn, BasisPtr basis, const FieldContainer<double> &physicalCellNodes) { CellTopoPtr cellTopo = basis->domainTopology(); DofOrderingPtr dofOrderPtr = Teuchos::rcp(new DofOrdering()); int basisRank = BasisFactory::basisFactory()->getBasisRank(basis); int ID = 0; // only one entry for this fake dofOrderPtr dofOrderPtr->addEntry(ID,basis,basisRank); int maxTrialDegree = dofOrderPtr->maxBasisDegree(); // do not build side caches - no projections for sides supported at the moment if (cellTopo->getTensorialDegree() != 0) { cout << "Projector::projectFunctionOntoBasis() does not yet support tensorial degree > 0.\n"; TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "Projector::projectFunctionOntoBasis() does not yet support tensorial degree > 0."); } shards::CellTopology shardsTopo = cellTopo->getShardsTopology(); BasisCache basisCache(physicalCellNodes, shardsTopo, *(dofOrderPtr), maxTrialDegree, false); // assume only L2 projections IntrepidExtendedTypes::EOperatorExtended op = IntrepidExtendedTypes::OP_VALUE; // have information, build inner product matrix int numDofs = basis->getCardinality(); FieldContainer<double> cubPoints = basisCache.getPhysicalCubaturePoints(); FieldContainer<double> basisValues = *(basisCache.getTransformedValues(basis, op)); FieldContainer<double> testBasisValues = *(basisCache.getTransformedWeightedValues(basis, op)); int numCells = physicalCellNodes.dimension(0); int numPts = cubPoints.dimension(1); FieldContainer<double> functionValues; fxn->getValues(functionValues, cubPoints); FieldContainer<double> gramMatrix(numCells,numDofs,numDofs); FieldContainer<double> ipVector(numCells,numDofs); FunctionSpaceTools::integrate<double>(gramMatrix,basisValues,testBasisValues,COMP_BLAS); FunctionSpaceTools::integrate<double>(ipVector,functionValues,testBasisValues,COMP_BLAS); basisCoefficients.resize(numCells,numDofs); for (int cellIndex=0; cellIndex<numCells; cellIndex++){ Epetra_SerialDenseSolver solver; Epetra_SerialDenseMatrix A(Copy, &gramMatrix(cellIndex,0,0), gramMatrix.dimension(2), gramMatrix.dimension(2), gramMatrix.dimension(1)); // stride -- fc stores in row-major order (a.o.t. SDM) Epetra_SerialDenseVector b(Copy, &ipVector(cellIndex,0), ipVector.dimension(1)); Epetra_SerialDenseVector x(gramMatrix.dimension(1)); /* cout << "matrix A = " << endl; for (int i=0;i<gramMatrix.dimension(2);i++){ for (int j=0;j<gramMatrix.dimension(1);j++){ cout << A(i,j) << " "; } cout << endl; } cout << endl; cout << "vector B = " << endl; for (int i=0;i<functionValues.dimension(1);i++){ cout << b(i) << endl; } */ solver.SetMatrix(A); int info = solver.SetVectors(x,b); if (info!=0){ cout << "projectFunctionOntoBasis: failed to SetVectors with error " << info << endl; } bool equilibrated = false; if (solver.ShouldEquilibrate()){ solver.EquilibrateMatrix(); solver.EquilibrateRHS(); equilibrated = true; } info = solver.Solve(); if (info!=0){ cout << "projectFunctionOntoBasis: failed to solve with error " << info << endl; } if (equilibrated) { int successLocal = solver.UnequilibrateLHS(); if (successLocal != 0) { cout << "projection: unequilibration FAILED with error: " << successLocal << endl; } } for (int i=0;i<numDofs;i++){ basisCoefficients(cellIndex,i) = x(i); } } }