コード例 #1
0
std::pair<unsigned int, Real>
LaspackLinearSolver<T>::adjoint_solve (SparseMatrix<T> &matrix_in,
                                       NumericVector<T> &solution_in,
                                       NumericVector<T> &rhs_in,
                                       const double tol,
                                       const unsigned int m_its)
{
  START_LOG("adjoint_solve()", "LaspackLinearSolver");
  this->init ();

  // Make sure the data passed in are really in Laspack types
  LaspackMatrix<T>* matrix   = cast_ptr<LaspackMatrix<T>*>(&matrix_in);
  LaspackVector<T>* solution = cast_ptr<LaspackVector<T>*>(&solution_in);
  LaspackVector<T>* rhs      = cast_ptr<LaspackVector<T>*>(&rhs_in);

  // Zero-out the solution to prevent the solver from exiting in 0
  // iterations (?)
  //TODO:[BSK] Why does Laspack do this?  Comment out this and try ex13...
  solution->zero();

  // Close the matrix and vectors in case this wasn't already done.
  matrix->close ();
  solution->close ();
  rhs->close ();

  // Set the preconditioner type
  this->set_laspack_preconditioner_type ();

  // Set the solver tolerance
  SetRTCAccuracy (tol);

  // Solve the linear system
  switch (this->_solver_type)
    {
      // Conjugate-Gradient
    case CG:
      {
        CGIter (Transp_Q(&matrix->_QMat),
                &solution->_vec,
                &rhs->_vec,
                m_its,
                _precond_type,
                1.);
        break;
      }

      // Conjugate-Gradient Normalized
    case CGN:
      {
        CGNIter (Transp_Q(&matrix->_QMat),
                 &solution->_vec,
                 &rhs->_vec,
                 m_its,
                 _precond_type,
                 1.);
        break;
      }

      // Conjugate-Gradient Squared
    case CGS:
      {
        CGSIter (Transp_Q(&matrix->_QMat),
                 &solution->_vec,
                 &rhs->_vec,
                 m_its,
                 _precond_type,
                 1.);
        break;
      }

      // Bi-Conjugate Gradient
    case BICG:
      {
        BiCGIter (Transp_Q(&matrix->_QMat),
                  &solution->_vec,
                  &rhs->_vec,
                  m_its,
                  _precond_type,
                  1.);
        break;
      }

      // Bi-Conjugate Gradient Stabilized
    case BICGSTAB:
      {
        BiCGSTABIter (Transp_Q(&matrix->_QMat),
                      &solution->_vec,
                      &rhs->_vec,
                      m_its,
                      _precond_type,
                      1.);
        break;
      }

      // Quasi-Minimum Residual
    case QMR:
      {
        QMRIter (Transp_Q(&matrix->_QMat),
                 &solution->_vec,
                 &rhs->_vec,
                 m_its,
                 _precond_type,
                 1.);
        break;
      }

      // Symmetric over-relaxation
    case SSOR:
      {
        SSORIter (Transp_Q(&matrix->_QMat),
                  &solution->_vec,
                  &rhs->_vec,
                  m_its,
                  _precond_type,
                  1.);
        break;
      }

      // Jacobi Relaxation
    case JACOBI:
      {
        JacobiIter (Transp_Q(&matrix->_QMat),
                    &solution->_vec,
                    &rhs->_vec,
                    m_its,
                    _precond_type,
                    1.);
        break;
      }

      // Generalized Minimum Residual
    case GMRES:
      {
        SetGMRESRestart (30);
        GMRESIter (Transp_Q(&matrix->_QMat),
                   &solution->_vec,
                   &rhs->_vec,
                   m_its,
                   _precond_type,
                   1.);
        break;
      }

      // Unknown solver, use GMRES
    default:
      {
        libMesh::err << "ERROR:  Unsupported LASPACK Solver: "
                     << Utility::enum_to_string(this->_solver_type) << std::endl
                     << "Continuing with GMRES" << std::endl;

        this->_solver_type = GMRES;

        return this->solve (*matrix,
                            *solution,
                            *rhs,
                            tol,
                            m_its);
      }
    }

  // Check for an error
  if (LASResult() != LASOK)
    {
      WriteLASErrDescr(stdout);
      libmesh_error_msg("Exiting after LASPACK Error!");
    }

  STOP_LOG("adjoint_solve()", "LaspackLinearSolver");
  // Get the convergence step # and residual
  return std::make_pair(GetLastNoIter(), GetLastAccuracy());
}
コード例 #2
0
ファイル: eigenval.c プロジェクト: jumpinsky/diff_equations
static void EstimEigenvals(QMatrix *A, PrecondProcType PrecondProc, double OmegaPrecond)
/* estimates extremal eigenvalues of the matrix A by means of the Lanczos method */
{
    /*
     *  for details to the Lanczos algorithm see
     *
     *  G. H. Golub, Ch. F. van Loan:
     *  Matrix Computations;
     *  North Oxford Academic, Oxford, 1986
     *
     *  (for modification for preconditioned matrices compare with sec. 10.3) 
     *
     */
   
    double LambdaMin = 0.0, LambdaMax = 0.0;
    double LambdaMinOld, LambdaMaxOld;
    double GershBoundMin = 0.0, GershBoundMax = 0.0;
    double *Alpha, *Beta;
    size_t Dim, j;
    Boolean Found;
    Vector q, qOld, h, p;

    Q_Lock(A);
    
    Dim = Q_GetDim(A);
    V_Constr(&q, "q", Dim, Normal, True);
    V_Constr(&qOld, "qOld", Dim, Normal, True);
    V_Constr(&h, "h", Dim, Normal, True);
    if (PrecondProc != NULL)
        V_Constr(&p, "p", Dim, Normal, True);
   
    if (LASResult() == LASOK) {
        Alpha = (double *)malloc((Dim + 1) * sizeof(double));
        Beta = (double *)malloc((Dim + 1) * sizeof(double));
        if (Alpha != NULL && Beta != NULL) {
	    j = 0;
            
            V_SetAllCmp(&qOld, 0.0);
            V_SetRndCmp(&q);
	    if (Q_KerDefined(A))
	        OrthoRightKer_VQ(&q, A);
            if (Q_GetSymmetry(A) && PrecondProc != NULL) {
	        (*PrecondProc)(A, &p, &q, OmegaPrecond);
                MulAsgn_VS(&q, 1.0 / sqrt(Mul_VV(&q, &p)));
	    } else {
                MulAsgn_VS(&q, 1.0 / l2Norm_V(&q));
	    }
            
            Beta[0] = 1.0;
            do {
	        j++;
                if (Q_GetSymmetry(A) && PrecondProc != NULL) {
		    /* p = M^(-1) q */
		    (*PrecondProc)(A, &p, &q, OmegaPrecond);
		    /* h = A p */
                    Asgn_VV(&h, Mul_QV(A, &p));
	            if (Q_KerDefined(A))
	                OrthoRightKer_VQ(&h, A);
		    /* Alpha = p . h */
                    Alpha[j] = Mul_VV(&p, &h);
		    /* r = h - Alpha q - Beta qOld */
                    SubAsgn_VV(&h, Add_VV(Mul_SV(Alpha[j], &q), Mul_SV(Beta[j-1], &qOld)));
                    /* z = M^(-1) r */
		    (*PrecondProc)(A, &p, &h, OmegaPrecond);
		    /* Beta = sqrt(r . z) */
                    Beta[j] = sqrt(Mul_VV(&h, &p));
                    Asgn_VV(&qOld, &q);
		    /* q = r / Beta */
                    Asgn_VV(&q, Mul_SV(1.0 / Beta[j], &h));
		} else {
		    /* h = A p */
  		    if (Q_GetSymmetry(A)) {
                        Asgn_VV(&h, Mul_QV(A, &q));
		    } else {
                        if (PrecondProc != NULL) {
			    (*PrecondProc)(A, &h, Mul_QV(A, &q), OmegaPrecond);
			    (*PrecondProc)(Transp_Q(A), &h, &h, OmegaPrecond);
                            Asgn_VV(&h, Mul_QV(Transp_Q(A), &h));
                        } else {
                            Asgn_VV(&h, Mul_QV(Transp_Q(A), Mul_QV(A, &q)));
                        }
                    }
	            if (Q_KerDefined(A))
	                OrthoRightKer_VQ(&h, A); 
		    /* Alpha = q . h */
                    Alpha[j] = Mul_VV(&q, &h);
		    /* r = h - Alpha q - Beta qOld */
                    SubAsgn_VV(&h, Add_VV(Mul_SV(Alpha[j], &q), Mul_SV(Beta[j-1], &qOld)));
                    /* Beta = || r || */
		    Beta[j] = l2Norm_V(&h);
                    Asgn_VV(&qOld, &q);
		    /* q = r / Beta */
                    Asgn_VV(&q, Mul_SV(1.0 / Beta[j], &h));
		}
		
		LambdaMaxOld = LambdaMax;
                LambdaMinOld = LambdaMin;
		
                /* determination of extremal eigenvalues of the tridiagonal matrix
                   (Beta[i-1] Alpha[i] Beta[i]) (where 1 <= i <= j) 
		   by means of the method of bisection; bounds for eigenvalues
		   are determined after Gershgorin circle theorem */
                if (j == 1) {
		    GershBoundMin = Alpha[1] - fabs(Beta[1]);
	  	    GershBoundMax = Alpha[1] + fabs(Beta[1]);
		    
                    LambdaMin = Alpha[1];
                    LambdaMax = Alpha[1];
		} else {
		    GershBoundMin = min(Alpha[j] - fabs(Beta[j]) - fabs(Beta[j - 1]),
					GershBoundMin);
		    GershBoundMax = max(Alpha[j] + fabs(Beta[j]) + fabs(Beta[j - 1]),
				        GershBoundMax);

                    SearchEigenval(j, Alpha, Beta, 1, GershBoundMin, LambdaMin,
		        &Found, &LambdaMin);
		    if (!Found)
                        SearchEigenval(j, Alpha, Beta, 1, GershBoundMin, GershBoundMax,
		            &Found, &LambdaMin);
		    
	            SearchEigenval(j, Alpha, Beta, j, LambdaMax, GershBoundMax,
		        &Found, &LambdaMax);
		    if (!Found)
                        SearchEigenval(j, Alpha, Beta, j, GershBoundMin, GershBoundMax,
		            &Found, &LambdaMax);
                }
            } while (!IsZero(Beta[j]) && j < Dim
		&& (fabs(LambdaMin - LambdaMinOld) > EigenvalEps * LambdaMin
                || fabs(LambdaMax - LambdaMaxOld) > EigenvalEps * LambdaMax)
                && LASResult() == LASOK);
                
	    if (Q_GetSymmetry(A)) {
	        LambdaMin = (1.0 - j * EigenvalEps) * LambdaMin;
	    } else {
	        LambdaMin = (1.0 - sqrt(j) * EigenvalEps) * sqrt(LambdaMin);
            }
            if (Alpha != NULL)
                free(Alpha);
            if (Beta != NULL)
                free(Beta);
        } else {
            LASError(LASMemAllocErr, "EstimEigenvals", Q_GetName(A), NULL, NULL);
	}

    }
    
    V_Destr(&q);
    V_Destr(&qOld);
    V_Destr(&h);
    if (PrecondProc != NULL)
        V_Destr(&p);
    
    if (LASResult() == LASOK) {
        ((EigenvalInfoType *)*(Q_EigenvalInfo(A)))->MinEigenval = LambdaMin;
        ((EigenvalInfoType *)*(Q_EigenvalInfo(A)))->MaxEigenval = LambdaMax;
        ((EigenvalInfoType *)*(Q_EigenvalInfo(A)))->PrecondProcUsed = PrecondProc;
        ((EigenvalInfoType *)*(Q_EigenvalInfo(A)))->OmegaPrecondUsed = OmegaPrecond;
    } else {
        ((EigenvalInfoType *)*(Q_EigenvalInfo(A)))->MinEigenval = 1.0;
        ((EigenvalInfoType *)*(Q_EigenvalInfo(A)))->MaxEigenval = 1.0;
        ((EigenvalInfoType *)*(Q_EigenvalInfo(A)))->PrecondProcUsed = NULL;
        ((EigenvalInfoType *)*(Q_EigenvalInfo(A)))->OmegaPrecondUsed = 1.0;
    }

    Q_Unlock(A);
}