void implicit_1Dx(double *phi, double *xx, double nu, double gamma, double h, double beta, double dt, int L, int use_delj_trick) { int ii; double *dx = malloc((L-1) * sizeof(*dx)); double *dfactor = malloc(L * sizeof(*dfactor)); double *xInt = malloc((L-1) * sizeof(*xInt)); double Mfirst, Mlast; double *MInt = malloc((L-1) * sizeof(*MInt)); double *V = malloc(L * sizeof(*V)); double *VInt = malloc((L-1) * sizeof(*VInt)); double *delj = malloc((L-1) * sizeof(*delj)); double *a = malloc(L * sizeof(*a)); double *b = malloc(L * sizeof(*b)); double *c = malloc(L * sizeof(*c)); double *r = malloc(L * sizeof(*r)); compute_dx(xx, L, dx); compute_dfactor(dx, L, dfactor); compute_xInt(xx, L, xInt); Mfirst = Mfunc1D(xx[0], gamma, h); Mlast = Mfunc1D(xx[L-1], gamma, h); for(ii=0; ii < L; ii++) V[ii] = Vfunc_beta(xx[ii], nu, beta); for(ii=0; ii < L-1; ii++) { MInt[ii] = Mfunc1D(xInt[ii], gamma, h); VInt[ii] = Vfunc_beta(xInt[ii], nu, beta); } compute_delj(dx, MInt, VInt, L, delj, use_delj_trick); compute_abc_nobc(dx, dfactor, delj, MInt, V, dt, L, a, b, c); for(ii = 0; ii < L; ii++) r[ii] = phi[ii]/dt; /* Boundary conditions */ if(Mfirst <= 0) b[0] += (0.5/nu - Mfirst)*2./dx[0]; if(Mlast >= 0) b[L-1] += -(-0.5/nu - Mlast)*2./dx[L-2]; tridiag(a, b, c, r, phi, L); free(dx); free(dfactor); free(xInt); free(MInt); free(V); free(VInt); free(delj); free(a); free(b); free(c); free(r); }
void poisson_r(double *q, int m, int NR, int NZ, double dr, double dz) { int j; double *a,*b,*c,*r,alpha,beta; alpha=2.0*(cos(2.0*PI*m/(NZ))-1.0)/pow(dz,2); beta=4.0/pow(dr,2); a = new double[NR]; b = new double[NR]; c = new double[NR]; r = new double[NR]; for(j=1; j<NR; j++) { a[j]=(1.0-0.5/((double)j))/pow(dr,2); c[j]=(1.0+0.5/((double)j))/pow(dr,2); b[j]=2.0*((cos(2.0*PI*m/(NZ))-1.0)/pow(dz,2)-1.0/pow(dr,2)); r[j]=-q[j]/eps0; } b[0]=alpha-beta; c[0]=beta; r[0]=-q[0]/eps0; tridiag(q,a,b,c,r,NR); delete a; delete b; delete c; delete r; }
template<typename MatrixType> void qr(const MatrixType& m) { /* this test covers the following files: QR.h */ int rows = m.rows(); int cols = m.cols(); typedef typename MatrixType::Scalar Scalar; typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, MatrixType::ColsAtCompileTime> SquareMatrixType; typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType; MatrixType a = MatrixType::Random(rows,cols); QR<MatrixType> qrOfA(a); VERIFY_IS_APPROX(a, qrOfA.matrixQ() * qrOfA.matrixR()); VERIFY_IS_NOT_APPROX(a+MatrixType::Identity(rows, cols), qrOfA.matrixQ() * qrOfA.matrixR()); SquareMatrixType b = a.adjoint() * a; // check tridiagonalization Tridiagonalization<SquareMatrixType> tridiag(b); VERIFY_IS_APPROX(b, tridiag.matrixQ() * tridiag.matrixT() * tridiag.matrixQ().adjoint()); // check hessenberg decomposition HessenbergDecomposition<SquareMatrixType> hess(b); VERIFY_IS_APPROX(b, hess.matrixQ() * hess.matrixH() * hess.matrixQ().adjoint()); VERIFY_IS_APPROX(tridiag.matrixT(), hess.matrixH()); b = SquareMatrixType::Random(cols,cols); hess.compute(b); VERIFY_IS_APPROX(b, hess.matrixQ() * hess.matrixH() * hess.matrixQ().adjoint()); }
BOOST_FORCEINLINE result_type operator()(A0 const& a0, A1 const& a1, A2 const& a2) const { return tridiag(nt2::repnum(a0, nt2::numel(a2), size_t(1)), a1, a2); }
typename meta::call<nt2::tag::tridiag_(const I&, nt2::meta::as_<T>) >::type tridiag(const I& n) { return tridiag(n, nt2::meta::as_<T>()); }
template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m) { typedef typename MatrixType::Index Index; /* this test covers the following files: EigenSolver.h, SelfAdjointEigenSolver.h (and indirectly: Tridiagonalization.h) */ Index rows = m.rows(); Index cols = m.cols(); typedef typename MatrixType::Scalar Scalar; typedef typename NumTraits<Scalar>::Real RealScalar; RealScalar largerEps = 10*test_precision<RealScalar>(); MatrixType a = MatrixType::Random(rows,cols); MatrixType a1 = MatrixType::Random(rows,cols); MatrixType symmA = a.adjoint() * a + a1.adjoint() * a1; MatrixType symmC = symmA; svd_fill_random(symmA,Symmetric); symmA.template triangularView<StrictlyUpper>().setZero(); symmC.template triangularView<StrictlyUpper>().setZero(); MatrixType b = MatrixType::Random(rows,cols); MatrixType b1 = MatrixType::Random(rows,cols); MatrixType symmB = b.adjoint() * b + b1.adjoint() * b1; symmB.template triangularView<StrictlyUpper>().setZero(); CALL_SUBTEST( selfadjointeigensolver_essential_check(symmA) ); SelfAdjointEigenSolver<MatrixType> eiSymm(symmA); // generalized eigen pb GeneralizedSelfAdjointEigenSolver<MatrixType> eiSymmGen(symmC, symmB); SelfAdjointEigenSolver<MatrixType> eiSymmNoEivecs(symmA, false); VERIFY_IS_EQUAL(eiSymmNoEivecs.info(), Success); VERIFY_IS_APPROX(eiSymm.eigenvalues(), eiSymmNoEivecs.eigenvalues()); // generalized eigen problem Ax = lBx eiSymmGen.compute(symmC, symmB,Ax_lBx); VERIFY_IS_EQUAL(eiSymmGen.info(), Success); VERIFY((symmC.template selfadjointView<Lower>() * eiSymmGen.eigenvectors()).isApprox( symmB.template selfadjointView<Lower>() * (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps)); // generalized eigen problem BAx = lx eiSymmGen.compute(symmC, symmB,BAx_lx); VERIFY_IS_EQUAL(eiSymmGen.info(), Success); VERIFY((symmB.template selfadjointView<Lower>() * (symmC.template selfadjointView<Lower>() * eiSymmGen.eigenvectors())).isApprox( (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps)); // generalized eigen problem ABx = lx eiSymmGen.compute(symmC, symmB,ABx_lx); VERIFY_IS_EQUAL(eiSymmGen.info(), Success); VERIFY((symmC.template selfadjointView<Lower>() * (symmB.template selfadjointView<Lower>() * eiSymmGen.eigenvectors())).isApprox( (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps)); eiSymm.compute(symmC); MatrixType sqrtSymmA = eiSymm.operatorSqrt(); VERIFY_IS_APPROX(MatrixType(symmC.template selfadjointView<Lower>()), sqrtSymmA*sqrtSymmA); VERIFY_IS_APPROX(sqrtSymmA, symmC.template selfadjointView<Lower>()*eiSymm.operatorInverseSqrt()); MatrixType id = MatrixType::Identity(rows, cols); VERIFY_IS_APPROX(id.template selfadjointView<Lower>().operatorNorm(), RealScalar(1)); SelfAdjointEigenSolver<MatrixType> eiSymmUninitialized; VERIFY_RAISES_ASSERT(eiSymmUninitialized.info()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvalues()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt()); eiSymmUninitialized.compute(symmA, false); VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt()); // test Tridiagonalization's methods Tridiagonalization<MatrixType> tridiag(symmC); VERIFY_IS_APPROX(tridiag.diagonal(), tridiag.matrixT().diagonal()); VERIFY_IS_APPROX(tridiag.subDiagonal(), tridiag.matrixT().template diagonal<-1>()); Matrix<RealScalar,Dynamic,Dynamic> T = tridiag.matrixT(); if(rows>1 && cols>1) { // FIXME check that upper and lower part are 0: //VERIFY(T.topRightCorner(rows-2, cols-2).template triangularView<Upper>().isZero()); } VERIFY_IS_APPROX(tridiag.diagonal(), T.diagonal()); VERIFY_IS_APPROX(tridiag.subDiagonal(), T.template diagonal<1>()); VERIFY_IS_APPROX(MatrixType(symmC.template selfadjointView<Lower>()), tridiag.matrixQ() * tridiag.matrixT().eval() * MatrixType(tridiag.matrixQ()).adjoint()); VERIFY_IS_APPROX(MatrixType(symmC.template selfadjointView<Lower>()), tridiag.matrixQ() * tridiag.matrixT() * tridiag.matrixQ().adjoint()); // Test computation of eigenvalues from tridiagonal matrix if(rows > 1) { SelfAdjointEigenSolver<MatrixType> eiSymmTridiag; eiSymmTridiag.computeFromTridiagonal(tridiag.matrixT().diagonal(), tridiag.matrixT().diagonal(-1), ComputeEigenvectors); VERIFY_IS_APPROX(eiSymm.eigenvalues(), eiSymmTridiag.eigenvalues()); VERIFY_IS_APPROX(tridiag.matrixT(), eiSymmTridiag.eigenvectors().real() * eiSymmTridiag.eigenvalues().asDiagonal() * eiSymmTridiag.eigenvectors().real().transpose()); } if (rows > 1) { // Test matrix with NaN symmC(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN(); SelfAdjointEigenSolver<MatrixType> eiSymmNaN(symmC); VERIFY_IS_EQUAL(eiSymmNaN.info(), NoConvergence); } }
template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m) { typedef typename MatrixType::Index Index; /* this test covers the following files: EigenSolver.h, SelfAdjointEigenSolver.h (and indirectly: Tridiagonalization.h) */ Index rows = m.rows(); Index cols = m.cols(); typedef typename MatrixType::Scalar Scalar; typedef typename NumTraits<Scalar>::Real RealScalar; typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType; typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType; typedef typename std::complex<typename NumTraits<typename MatrixType::Scalar>::Real> Complex; RealScalar largerEps = 10*test_precision<RealScalar>(); MatrixType a = MatrixType::Random(rows,cols); MatrixType a1 = MatrixType::Random(rows,cols); MatrixType symmA = a.adjoint() * a + a1.adjoint() * a1; symmA.template triangularView<StrictlyUpper>().setZero(); MatrixType b = MatrixType::Random(rows,cols); MatrixType b1 = MatrixType::Random(rows,cols); MatrixType symmB = b.adjoint() * b + b1.adjoint() * b1; symmB.template triangularView<StrictlyUpper>().setZero(); SelfAdjointEigenSolver<MatrixType> eiSymm(symmA); // generalized eigen pb GeneralizedSelfAdjointEigenSolver<MatrixType> eiSymmGen(symmA, symmB); #ifdef HAS_GSL if (internal::is_same<RealScalar,double>::value) { // restore symmA and symmB. symmA = MatrixType(symmA.template selfadjointView<Lower>()); symmB = MatrixType(symmB.template selfadjointView<Lower>()); typedef GslTraits<Scalar> Gsl; typename Gsl::Matrix gEvec=0, gSymmA=0, gSymmB=0; typename GslTraits<RealScalar>::Vector gEval=0; RealVectorType _eval; MatrixType _evec; convert<MatrixType>(symmA, gSymmA); convert<MatrixType>(symmB, gSymmB); convert<MatrixType>(symmA, gEvec); gEval = GslTraits<RealScalar>::createVector(rows); Gsl::eigen_symm(gSymmA, gEval, gEvec); convert(gEval, _eval); convert(gEvec, _evec); // test gsl itself ! VERIFY((symmA * _evec).isApprox(_evec * _eval.asDiagonal(), largerEps)); // compare with eigen VERIFY_IS_APPROX(_eval, eiSymm.eigenvalues()); VERIFY_IS_APPROX(_evec.cwiseAbs(), eiSymm.eigenvectors().cwiseAbs()); // generalized pb Gsl::eigen_symm_gen(gSymmA, gSymmB, gEval, gEvec); convert(gEval, _eval); convert(gEvec, _evec); // test GSL itself: VERIFY((symmA * _evec).isApprox(symmB * (_evec * _eval.asDiagonal()), largerEps)); // compare with eigen MatrixType normalized_eivec = eiSymmGen.eigenvectors()*eiSymmGen.eigenvectors().colwise().norm().asDiagonal().inverse(); VERIFY_IS_APPROX(_eval, eiSymmGen.eigenvalues()); VERIFY_IS_APPROX(_evec.cwiseAbs(), normalized_eivec.cwiseAbs()); Gsl::free(gSymmA); Gsl::free(gSymmB); GslTraits<RealScalar>::free(gEval); Gsl::free(gEvec); } #endif VERIFY_IS_EQUAL(eiSymm.info(), Success); VERIFY((symmA.template selfadjointView<Lower>() * eiSymm.eigenvectors()).isApprox( eiSymm.eigenvectors() * eiSymm.eigenvalues().asDiagonal(), largerEps)); VERIFY_IS_APPROX(symmA.template selfadjointView<Lower>().eigenvalues(), eiSymm.eigenvalues()); SelfAdjointEigenSolver<MatrixType> eiSymmNoEivecs(symmA, false); VERIFY_IS_EQUAL(eiSymmNoEivecs.info(), Success); VERIFY_IS_APPROX(eiSymm.eigenvalues(), eiSymmNoEivecs.eigenvalues()); // generalized eigen problem Ax = lBx eiSymmGen.compute(symmA, symmB,Ax_lBx); VERIFY_IS_EQUAL(eiSymmGen.info(), Success); VERIFY((symmA.template selfadjointView<Lower>() * eiSymmGen.eigenvectors()).isApprox( symmB.template selfadjointView<Lower>() * (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps)); // generalized eigen problem BAx = lx eiSymmGen.compute(symmA, symmB,BAx_lx); VERIFY_IS_EQUAL(eiSymmGen.info(), Success); VERIFY((symmB.template selfadjointView<Lower>() * (symmA.template selfadjointView<Lower>() * eiSymmGen.eigenvectors())).isApprox( (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps)); // generalized eigen problem ABx = lx eiSymmGen.compute(symmA, symmB,ABx_lx); VERIFY_IS_EQUAL(eiSymmGen.info(), Success); VERIFY((symmA.template selfadjointView<Lower>() * (symmB.template selfadjointView<Lower>() * eiSymmGen.eigenvectors())).isApprox( (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps)); MatrixType sqrtSymmA = eiSymm.operatorSqrt(); VERIFY_IS_APPROX(MatrixType(symmA.template selfadjointView<Lower>()), sqrtSymmA*sqrtSymmA); VERIFY_IS_APPROX(sqrtSymmA, symmA.template selfadjointView<Lower>()*eiSymm.operatorInverseSqrt()); MatrixType id = MatrixType::Identity(rows, cols); VERIFY_IS_APPROX(id.template selfadjointView<Lower>().operatorNorm(), RealScalar(1)); SelfAdjointEigenSolver<MatrixType> eiSymmUninitialized; VERIFY_RAISES_ASSERT(eiSymmUninitialized.info()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvalues()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt()); eiSymmUninitialized.compute(symmA, false); VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt()); // test Tridiagonalization's methods Tridiagonalization<MatrixType> tridiag(symmA); // FIXME tridiag.matrixQ().adjoint() does not work VERIFY_IS_APPROX(MatrixType(symmA.template selfadjointView<Lower>()), tridiag.matrixQ() * tridiag.matrixT().eval() * MatrixType(tridiag.matrixQ()).adjoint()); if (rows > 1) { // Test matrix with NaN symmA(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN(); SelfAdjointEigenSolver<MatrixType> eiSymmNaN(symmA); VERIFY_IS_EQUAL(eiSymmNaN.info(), NoConvergence); } }
int main(void) { int i, j, n, wahl; double vektor[NMAX]; double matrix[NMAX][NMAX]; printf("\n Bitte geben Sie die Spaltenzahl der zu erzeugenden Matrix ein : "); scanf("%d",&n); if (n > NMAX) { printf("\n\nArraygrenze überschritten - NMAX muß größer gewählt werden !"); exit(1); } else { printf("\n Welchen Typ von Matrix wollen Sie erzeugen : \n"); printf("\n Einheitsmatrix 1"); printf("\n Nullmatrix 2"); printf("\n Symmetr. Zufallsmatrix 3"); printf("\n Trigonalmatrix 4"); printf("\n\nBitte treffen Sie eine Wahl : "); scanf("%d",&wahl); switch(wahl) { case 1: ident(n,matrix); break; case 2: zeros(n,matrix); break; case 3: randsym(n,matrix); break; case 4: printf("\nBitte geben Sie den zu übergebenden Diagonalvektor ein :\n\n"); for (i=0; i<n; i++) { printf("%2d.-te Komponente des Vektors : ",i+1); scanf("%lg",&vektor[i]); } tridiag(n,matrix,vektor); break; default: exit(1); } printf("\n\n\t"); for (i=0; i<n; i++) { for (j=0; j<n; j++) printf(" %2lg",matrix[i][j]); printf("\n\t"); } printf("\n\n"); } return 0; }
long BiCGSTAB_upper(double tol_rel, double tol_min, double tol_max, DOUBLEVECTOR *x, DOUBLEVECTOR *b, LONGVECTOR *Ai, LONGVECTOR *Ap, DOUBLEVECTOR *Ax){ DOUBLEVECTOR *r0, *r, *p, *v, *s, *t, *diag, *udiag, *y, *z; double rho, rho1, alpha, omeg, beta, norm_r0; long i=0, j; r0 = new_doublevector(x->nh); r = new_doublevector(x->nh); p = new_doublevector(x->nh); v = new_doublevector(x->nh); s = new_doublevector(x->nh); t = new_doublevector(x->nh); diag = new_doublevector(x->nh); udiag = new_doublevector(x->nh-1); y = new_doublevector(x->nh); z = new_doublevector(x->nh); get_diag_upper_matrix(diag, udiag, Ai, Ap, Ax); product_using_only_upper_diagonal_part(r, x, Ai, Ap, Ax); for (j=x->nl;j<=x->nh;j++ ) { r->co[j] = b->co[j] - r->co[j]; r0->co[j] = r->co[j]; p->co[j] = 0.; v->co[j] = 0.; } norm_r0 = norm_2(r0,r0->nh); rho = 1.; alpha = 1.; omeg = 1.; while ( i<=x->nh && norm_2(r,r->nh) > Fmax( tol_min , Fmin( tol_max , tol_rel*norm_r0) ) ) { rho1 = product(r0, r); beta = (rho1/rho)*(alpha/omeg); rho = rho1; for (j=x->nl;j<=x->nh;j++ ) { p->co[j] = r->co[j] + beta*(p->co[j] - omeg*v->co[j]); } tridiag(0, 0, 0, x->nh, udiag, diag, udiag, p, y); product_using_only_upper_diagonal_part(v, y, Ai, Ap, Ax); alpha = rho/product(r0, v); for (j=x->nl;j<=x->nh;j++ ) { s->co[j] = r->co[j] - alpha*v->co[j]; } tridiag(0, 0, 0, x->nh, udiag, diag, udiag, s, z); product_using_only_upper_diagonal_part(t, z, Ai, Ap, Ax); omeg = product(t, s)/product(t, t); for (j=x->nl;j<=x->nh;j++ ) { x->co[j] += (alpha*y->co[j] + omeg*z->co[j]); r->co[j] = s->co[j] - omeg*t->co[j]; } i++; //printf("i:%ld normr0:%e normr:%e\n",i,norm_r0,norm_2(r,r->nh)); } free_doublevector(r0); free_doublevector(r); free_doublevector(p); free_doublevector(v); free_doublevector(s); free_doublevector(t); free_doublevector(diag); free_doublevector(udiag); free_doublevector(y); free_doublevector(z); return i; }
long BiCGSTAB(double tol_rel, double tol_min, double tol_max, DOUBLEVECTOR *x, DOUBLEVECTOR *x0, double dt, DOUBLEVECTOR *b, t_Matrix_element_with_voidp function, void *data){ /* \author Stefano Endrizzi \date March 2010 from BI-CGSTAB: A FAST AND SMOOTHLY CONVERGING VARIANT OF BI-CG FOR THE SOLUTION OF NONSYMMETRIC LINEAR SYSTEMS by H. A. VAN DER VORST - SIAM J. ScI. STAT. COMPUT. Vol. 13, No. 2, pp. 631-644, March 1992 */ DOUBLEVECTOR *r0, *r, *p, *v, *s, *t, *diag, *udiag, *y, *z; //DOUBLEVECTOR *tt, *ss; double rho, rho1, alpha, omeg, beta, norm_r0; long i=0, j; r0 = new_doublevector(x->nh); r = new_doublevector(x->nh); p = new_doublevector(x->nh); v = new_doublevector(x->nh); s = new_doublevector(x->nh); t = new_doublevector(x->nh); diag = new_doublevector(x->nh); udiag = new_doublevector(x->nh-1); y = new_doublevector(x->nh); z = new_doublevector(x->nh); //tt = new_doublevector(x->nh); //ss = new_doublevector(x->nh); get_diagonal(diag,x0,dt,function,data); get_upper_diagonal(udiag,x0,dt,function,data); for (j=x->nl;j<=x->nh;j++ ) { r0->co[j] = b->co[j] - (*function)(j,x,x0,dt,data); r->co[j] = r0->co[j]; p->co[j] = 0.; v->co[j] = 0.; } norm_r0 = norm_2(r0,r0->nh); rho = 1.; alpha = 1.; omeg = 1.; while ( i<=x->nh && norm_2(r,r->nh) > Fmax( tol_min , Fmin( tol_max , tol_rel*norm_r0) ) ) { rho1 = product(r0, r); beta = (rho1/rho)*(alpha/omeg); rho = rho1; for (j=x->nl;j<=x->nh;j++ ) { p->co[j] = r->co[j] + beta*(p->co[j] - omeg*v->co[j]); } tridiag(0, 0, 0, x->nh, udiag, diag, udiag, p, y); for (j=x->nl;j<=x->nh;j++ ) { v->co[j] = (*function)(j,y,x0,dt,data); } alpha = rho/product(r0, v); for (j=x->nl;j<=x->nh;j++ ) { s->co[j] = r->co[j] - alpha*v->co[j]; } tridiag(0, 0, 0, x->nh, udiag, diag, udiag, s, z); for (j=x->nl;j<=x->nh;j++ ) { t->co[j] = (*function)(j,z,x0,dt,data); } /*tridiag(0, 0, 0, x->nh, udiag, diag, udiag, t, tt); tridiag(0, 0, 0, x->nh, udiag, diag, udiag, s, ss); omeg = product(tt, ss)/product(tt, tt);*/ omeg = product(t, s)/product(t, t); for (j=x->nl;j<=x->nh;j++ ) { x->co[j] += (alpha*y->co[j] + omeg*z->co[j]); r->co[j] = s->co[j] - omeg*t->co[j]; } i++; //printf("i:%ld normr0:%e normr:%e\n",i,norm_r0,norm_2(r,r->nh)); } free_doublevector(r0); free_doublevector(r); free_doublevector(p); free_doublevector(v); free_doublevector(s); free_doublevector(t); free_doublevector(diag); free_doublevector(udiag); free_doublevector(y); free_doublevector(z); //free_doublevector(tt); //free_doublevector(ss); return i; }
long BiCGSTAB_strict_lower_matrix_plus_identity_by_vector(double tol_rel, double tol_min, double tol_max, DOUBLEVECTOR *x, DOUBLEVECTOR *b, DOUBLEVECTOR *y, LONGVECTOR *Li, LONGVECTOR *Lp, DOUBLEVECTOR *Lx){ //solve sistem (A+Iy)*x = B, find x //A M-matrix described by its lower diagonal part DOUBLEVECTOR *r0, *r, *p, *v, *s, *t, *diag, *udiag, *yy, *z; double rho, rho1, alpha, omeg, beta, norm_r0; long i=0, j; r0 = new_doublevector(x->nh); r = new_doublevector(x->nh); p = new_doublevector(x->nh); v = new_doublevector(x->nh); s = new_doublevector(x->nh); t = new_doublevector(x->nh); diag = new_doublevector(x->nh); udiag = new_doublevector(x->nh-1); yy = new_doublevector(x->nh); z = new_doublevector(x->nh); get_diag_strict_lower_matrix_plus_identity_by_vector(diag, udiag, y, Li, Lp, Lx); //product_using_only_strict_lower_diagonal_part_plus_identity_by_vector(r, x, y, Li, Lp, Lx); for (j=x->nl;j<=x->nh;j++ ) { //r->co[j] = b->co[j] - r->co[j]; r->co[j] = b->co[j]; r0->co[j] = r->co[j]; p->co[j] = 0.; v->co[j] = 0.; } norm_r0 = norm_2(r0,r0->nh); rho = 1.; alpha = 1.; omeg = 1.; while ( i<=x->nh && norm_2(r,r->nh) > Fmax( tol_min , Fmin( tol_max , tol_rel*norm_r0) ) ) { rho1 = product(r0, r); beta = (rho1/rho)*(alpha/omeg); rho = rho1; for (j=x->nl;j<=x->nh;j++ ) { p->co[j] = r->co[j] + beta*(p->co[j] - omeg*v->co[j]); } tridiag(0, 0, 0, x->nh, udiag, diag, udiag, p, yy); product_using_only_strict_lower_diagonal_part_plus_identity_by_vector(v, yy, y, Li, Lp, Lx); alpha = rho/product(r0, v); for (j=x->nl;j<=x->nh;j++ ) { s->co[j] = r->co[j] - alpha*v->co[j]; } if(norm_2(s,s->nh)>1.E-10){ tridiag(0, 0, 0, x->nh, udiag, diag, udiag, s, z); product_using_only_strict_lower_diagonal_part_plus_identity_by_vector(t, z, y, Li, Lp, Lx); omeg = product(t, s)/product(t, t); for (j=x->nl;j<=x->nh;j++ ) { x->co[j] += (alpha*yy->co[j] + omeg*z->co[j]); r->co[j] = s->co[j] - omeg*t->co[j]; } }else{ for (j=x->nl;j<=x->nh;j++ ) { x->co[j] += alpha*yy->co[j]; r->co[j] = s->co[j]; } } i++; //printf("i:%ld normr0:%e normr:%e\n",i,norm_r0,norm_2(r,r->nh)); } free_doublevector(r0); free_doublevector(r); free_doublevector(p); free_doublevector(v); free_doublevector(s); free_doublevector(t); free_doublevector(diag); free_doublevector(udiag); free_doublevector(yy); free_doublevector(z); return i; }
long CG(double tol_rel, double tol_min, double tol_max, DOUBLEVECTOR *x, DOUBLEVECTOR *x0, double dt, DOUBLEVECTOR *b, t_Matrix_element_with_voidp function, void *data){ /*! *\param icnt - (long) number of reiterations *\param epsilon - (double) required tollerance (2-order norm of the residuals) *\param x - (DOUBLEVECTOR *) vector of the unknowns x in Ax=b *\param b - (DOUBLEVECTOR *) vector of b in Ax=b *\param funz - (t_Matrix_element_with_voidp) - (int) pointer to the application A (x and y doublevector y=A(param)x ) it return 0 in case of success, -1 otherwise. *\param data - (void *) data and parameters related to the argurment t_Matrix_element_with_voidp funz * * *\brief algorithm proposed by Jonathan Richard Shewckuck in http://www.cs.cmu.edu/~jrs/jrspapers.html#cg and http://www.cs.cmu.edu/~quake-papers/painless-conjugate-gradient.pdf * * \author Emanuele Cordano * \date June 2009 * *\return the number of reitarations */ double delta,alpha,beta,delta_new; DOUBLEVECTOR *r, *d,*q,*y,*sr,*diag,*udiag; int sl; long icnt_max; long icnt; long j; double p; double norm_r0; r=new_doublevector(x->nh); d=new_doublevector(x->nh); q=new_doublevector(x->nh); y=new_doublevector(x->nh); sr=new_doublevector(x->nh); diag=new_doublevector(x->nh); udiag=new_doublevector(x->nh-1); icnt=0; icnt_max=x->nh; //icnt_max=(long)(sqrt((double)x->nh)); for (j=x->nl;j<=x->nh;j++){ y->co[j]=(*function)(j,x,x0,dt,data); } get_diagonal(diag,x0,dt,function,data); get_upper_diagonal(udiag,x0,dt,function,data); delta_new=0.0; for (j=y->nl;j<=y->nh;j++) { r->co[j]=b->co[j]-y->co[j]; if (diag->co[j]<0.0) { diag->co[j]=1.0; printf("\n Error in jacobi_preconditioned_conjugate_gradient_search function: diagonal of the matrix (%lf) is negative at %ld \n",diag->co[j],j); stop_execution(); } } tridiag(0,0,0,x->nh,udiag,diag,udiag,r,d); for (j=y->nl;j<=y->nh;j++) { //d->co[j]=r->co[j]/diag->co[j]; delta_new+=r->co[j]*d->co[j]; } norm_r0 = norm_2(r, r->nh); while ( icnt<=icnt_max && norm_2(r, r->nh) > Fmax( tol_min , Fmin( tol_max , tol_rel*norm_r0) ) ) { delta=delta_new; p=0.0; for(j=q->nl;j<=q->nh;j++) { q->co[j]=(*function)(j,d,x0,dt,data); p+=q->co[j]*d->co[j]; } alpha=delta_new/p; for(j=x->nl;j<=x->nh;j++) { x->co[j]=x->co[j]+alpha*d->co[j]; } delta_new=0.0; sl=0; for (j=y->nl;j<=y->nh;j++) { if (icnt%MAX_ITERATIONS==0) { y->co[j]=(*function)(j,x,x0,dt,data); r->co[j]=b->co[j]-y->co[j]; } else { r->co[j]=r->co[j]-alpha*q->co[j]; } } tridiag(0,0,0,x->nh,udiag,diag,udiag,r,sr); for (j=y->nl;j<=y->nh;j++) { delta_new+=sr->co[j]*r->co[j]; } beta=delta_new/delta; for (j=d->nl;j<=d->nh;j++) { d->co[j]=sr->co[j]+beta*d->co[j]; } icnt++; //printf("i:%ld normr0:%e normr:%e\n",icnt,norm_r0,norm_2(r,r->nh)); } //printf("norm_r:%e\n",norm_2(r,r->nh)); free_doublevector(udiag); free_doublevector(diag); free_doublevector(sr); free_doublevector(r); free_doublevector(d); free_doublevector(q); free_doublevector(y); return icnt; }
template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m) { typedef typename MatrixType::Index Index; /* this test covers the following files: EigenSolver.h, SelfAdjointEigenSolver.h (and indirectly: Tridiagonalization.h) */ Index rows = m.rows(); Index cols = m.cols(); typedef typename MatrixType::Scalar Scalar; typedef typename NumTraits<Scalar>::Real RealScalar; RealScalar largerEps = 10*test_precision<RealScalar>(); MatrixType a = MatrixType::Random(rows,cols); MatrixType a1 = MatrixType::Random(rows,cols); MatrixType symmA = a.adjoint() * a + a1.adjoint() * a1; MatrixType symmC = symmA; // randomly nullify some rows/columns { Index count = 1;//internal::random<Index>(-cols,cols); for(Index k=0; k<count; ++k) { Index i = internal::random<Index>(0,cols-1); symmA.row(i).setZero(); symmA.col(i).setZero(); } } symmA.template triangularView<StrictlyUpper>().setZero(); symmC.template triangularView<StrictlyUpper>().setZero(); MatrixType b = MatrixType::Random(rows,cols); MatrixType b1 = MatrixType::Random(rows,cols); MatrixType symmB = b.adjoint() * b + b1.adjoint() * b1; symmB.template triangularView<StrictlyUpper>().setZero(); SelfAdjointEigenSolver<MatrixType> eiSymm(symmA); SelfAdjointEigenSolver<MatrixType> eiDirect; eiDirect.computeDirect(symmA); // generalized eigen pb GeneralizedSelfAdjointEigenSolver<MatrixType> eiSymmGen(symmC, symmB); VERIFY_IS_EQUAL(eiSymm.info(), Success); VERIFY((symmA.template selfadjointView<Lower>() * eiSymm.eigenvectors()).isApprox( eiSymm.eigenvectors() * eiSymm.eigenvalues().asDiagonal(), largerEps)); VERIFY_IS_APPROX(symmA.template selfadjointView<Lower>().eigenvalues(), eiSymm.eigenvalues()); VERIFY_IS_EQUAL(eiDirect.info(), Success); VERIFY((symmA.template selfadjointView<Lower>() * eiDirect.eigenvectors()).isApprox( eiDirect.eigenvectors() * eiDirect.eigenvalues().asDiagonal(), largerEps)); VERIFY_IS_APPROX(symmA.template selfadjointView<Lower>().eigenvalues(), eiDirect.eigenvalues()); SelfAdjointEigenSolver<MatrixType> eiSymmNoEivecs(symmA, false); VERIFY_IS_EQUAL(eiSymmNoEivecs.info(), Success); VERIFY_IS_APPROX(eiSymm.eigenvalues(), eiSymmNoEivecs.eigenvalues()); // generalized eigen problem Ax = lBx eiSymmGen.compute(symmC, symmB,Ax_lBx); VERIFY_IS_EQUAL(eiSymmGen.info(), Success); VERIFY((symmC.template selfadjointView<Lower>() * eiSymmGen.eigenvectors()).isApprox( symmB.template selfadjointView<Lower>() * (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps)); // generalized eigen problem BAx = lx eiSymmGen.compute(symmC, symmB,BAx_lx); VERIFY_IS_EQUAL(eiSymmGen.info(), Success); VERIFY((symmB.template selfadjointView<Lower>() * (symmC.template selfadjointView<Lower>() * eiSymmGen.eigenvectors())).isApprox( (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps)); // generalized eigen problem ABx = lx eiSymmGen.compute(symmC, symmB,ABx_lx); VERIFY_IS_EQUAL(eiSymmGen.info(), Success); VERIFY((symmC.template selfadjointView<Lower>() * (symmB.template selfadjointView<Lower>() * eiSymmGen.eigenvectors())).isApprox( (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps)); eiSymm.compute(symmC); MatrixType sqrtSymmA = eiSymm.operatorSqrt(); VERIFY_IS_APPROX(MatrixType(symmC.template selfadjointView<Lower>()), sqrtSymmA*sqrtSymmA); VERIFY_IS_APPROX(sqrtSymmA, symmC.template selfadjointView<Lower>()*eiSymm.operatorInverseSqrt()); MatrixType id = MatrixType::Identity(rows, cols); VERIFY_IS_APPROX(id.template selfadjointView<Lower>().operatorNorm(), RealScalar(1)); SelfAdjointEigenSolver<MatrixType> eiSymmUninitialized; VERIFY_RAISES_ASSERT(eiSymmUninitialized.info()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvalues()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt()); eiSymmUninitialized.compute(symmA, false); VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt()); // test Tridiagonalization's methods Tridiagonalization<MatrixType> tridiag(symmC); // FIXME tridiag.matrixQ().adjoint() does not work VERIFY_IS_APPROX(MatrixType(symmC.template selfadjointView<Lower>()), tridiag.matrixQ() * tridiag.matrixT().eval() * MatrixType(tridiag.matrixQ()).adjoint()); if (rows > 1) { // Test matrix with NaN symmC(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN(); SelfAdjointEigenSolver<MatrixType> eiSymmNaN(symmC); VERIFY_IS_EQUAL(eiSymmNaN.info(), NoConvergence); } }