Example #1
0
  /*
   * Solve Ax = b. Vector b is overwritten on exit with x.
   */
  int SquareMatrix::solve(doublereal * b) 
  {
    if (useQR_) {
      return solveQR(b);
    }
    int info=0;
    /*
     * Check to see whether the matrix has been factored.
     */
    if (!m_factored) {
      int retn = factor();
      if (retn) {
	return retn;
      }
    }
    /*
     * Solve the factored system
     */
    ct_dgetrs(ctlapack::NoTranspose, static_cast<int>(nRows()),
	      1, &(*(begin())), static_cast<int>(nRows()), 
	      DATA_PTR(ipiv()), b, static_cast<int>(nColumns()), info);
    if (info != 0) {
      if (m_printLevel) {
	writelogf("SquareMatrix::solve(): DGETRS returned INFO = %d\n", info);
      }
      if (! m_useReturnErrorCode) {
	throw CELapackError("SquareMatrix::solve()", "DGETRS returned INFO = " + int2str(info));
      }
    }
    return info;
  }
Example #2
0
  //====================================================================================================================
  int solve(DenseMatrix& A, DenseMatrix& b) {
    int info = 0;
    if (A.nColumns() != A.nRows()) {
      if (A.m_printLevel) {
	writelogf("solve(DenseMatrix& A, DenseMatrix& b): Can only solve a square matrix\n");
      }  
      if (! A.m_useReturnErrorCode) {
	throw CELapackError("solve(DenseMatrix& A, DenseMatrix& b)", "Can only solve a square matrix");
      }
      return -1;
    }
    ct_dgetrf(static_cast<int>(A.nRows()), 
	      static_cast<int>(A.nColumns()), A.ptrColumn(0), 
	      static_cast<int>(A.nRows()), &A.ipiv()[0], info);
    if (info != 0) {
      if (info > 0) {
        if (A.m_printLevel) {
	  writelogf("solve(DenseMatrix& A, DenseMatrix& b): DGETRF returned INFO = %d   U(i,i) is exactly zero. The factorization has"
		    " been completed, but the factor U is exactly singular, and division by zero will occur if "
		    "it is used to solve a system of equations.\n", info);
        }
        if (! A.m_useReturnErrorCode) {
          throw CELapackError("solve(DenseMatrix& A, DenseMatrix& b)",
			     "DGETRF returned INFO = "+int2str(info) + ".   U(i,i) is exactly zero. The factorization has"
			     " been completed, but the factor U is exactly singular, and division by zero will occur if "
			     "it is used to solve a system of equations.");
        }
      } else {
	if (A.m_printLevel) {
	  writelogf("solve(DenseMatrix& A, DenseMatrix& b): DGETRF returned INFO = %d. The argument i has an illegal value\n", info);
	}
	if (! A.m_useReturnErrorCode) {
	  throw CELapackError("solve(DenseMatrix& A, DenseMatrix& b)",
			     "DGETRF returned INFO = "+int2str(info) + ". The argument i has an illegal value");
	}
      }
      return info;
    }
  
    ct_dgetrs(ctlapack::NoTranspose, static_cast<int>(A.nRows()),
	      static_cast<int>(b.nColumns()), 
	      A.ptrColumn(0), static_cast<int>(A.nRows()), 
	      &A.ipiv()[0], b.ptrColumn(0), 
	      static_cast<int>(b.nRows()), info);
    if (info != 0) {
      if (A.m_printLevel) {
	writelogf("solve(DenseMatrix& A, DenseMatrix& b): DGETRS returned INFO = %d\n", info);
      }
      if (! A.m_useReturnErrorCode) {
        throw CELapackError("solve(DenseMatrix& A, DenseMatrix& b)", "DGETRS returned INFO = "+int2str(info));
      }
    }
  
    return info;
  }
Example #3
0
 int solve(DenseMatrix& A, DenseMatrix& b) {
     int info=0;
     ct_dgetrf(static_cast<int>(A.nRows()), 
         static_cast<int>(A.nColumns()), A.ptrColumn(0), 
         static_cast<int>(A.nRows()), &A.ipiv()[0], info);
     if (info != 0) 
         throw CanteraError("DenseMatrix::solve",
             "DGETRF returned INFO = "+int2str(info)); 
     ct_dgetrs(ctlapack::NoTranspose, static_cast<int>(A.nRows()),
         static_cast<int>(b.nColumns()), 
         A.ptrColumn(0), static_cast<int>(A.nRows()), 
         &A.ipiv()[0], b.ptrColumn(0), 
         static_cast<int>(b.nRows()), info);
     if (info != 0)
         throw CanteraError("DenseMatrix::solve",
             "DGETRS returned INFO = "+int2str(info));
     return 0;
 }
Example #4
0
  /**
   * Solve Ax = b. Vector b is overwritten on exit with x.
   */
  int SquareMatrix::solve(double* b) 
  {
    int info=0;
    /*
     * Check to see whether the matrix has been factored.
     */
    if (!m_factored) {
      factor();
    }
    /*
     * Solve the factored system
     */
    ct_dgetrs(ctlapack::NoTranspose, static_cast<int>(nRows()),
	      1, &(*(begin())), static_cast<int>(nRows()), 
	      DATA_PTR(ipiv()), b, static_cast<int>(nColumns()), info);
    if (info != 0)
      throw CanteraError("SquareMatrix::solve",
			 "DGETRS returned INFO = "+int2str(info));
    return 0;
  }
Example #5
0
size_t BasisOptimize(int* usedZeroedSpecies, bool doFormRxn, MultiPhase* mphase,
                     std::vector<size_t>& orderVectorSpecies,
                     std::vector<size_t>& orderVectorElements,
                     vector_fp& formRxnMatrix)
{
    // Get the total number of elements defined in the multiphase object
    size_t ne = mphase->nElements();

    // Get the total number of species in the multiphase object
    size_t nspecies = mphase->nSpecies();

    // Perhaps, initialize the element ordering
    if (orderVectorElements.size() < ne) {
        orderVectorElements.resize(ne);
        iota(orderVectorElements.begin(), orderVectorElements.end(), 0);
    }

    // Perhaps, initialize the species ordering
    if (orderVectorSpecies.size() != nspecies) {
        orderVectorSpecies.resize(nspecies);
        iota(orderVectorSpecies.begin(), orderVectorSpecies.end(), 0);
    }

    if (BasisOptimize_print_lvl >= 1) {
        writelog("   ");
        writeline('-', 77);
        writelog("   --- Subroutine BASOPT called to ");
        writelog("calculate the number of components and ");
        writelog("evaluate the formation matrix\n");
        if (BasisOptimize_print_lvl > 0) {
            writelog("   ---\n");

            writelog("   ---      Formula Matrix used in BASOPT calculation\n");
            writelog("   ---      Species | Order | ");
            for (size_t j = 0; j < ne; j++) {
                size_t jj = orderVectorElements[j];
                writelog(" {:>4.4s}({:1d})", mphase->elementName(jj), j);
            }
            writelog("\n");
            for (size_t k = 0; k < nspecies; k++) {
                size_t kk = orderVectorSpecies[k];
                writelog("   --- {:>11.11s} |   {:4d} |",
                         mphase->speciesName(kk), k);
                for (size_t j = 0; j < ne; j++) {
                    size_t jj = orderVectorElements[j];
                    double num = mphase->nAtoms(kk,jj);
                    writelogf("%6.1g  ", num);
                }
                writelog("\n");
            }
            writelog("   --- \n");
        }
    }

    // Calculate the maximum value of the number of components possible. It's
    // equal to the minimum of the number of elements and the number of total
    // species.
    size_t nComponents = std::min(ne, nspecies);
    size_t nNonComponents = nspecies - nComponents;

    // Set this return variable to false
    *usedZeroedSpecies = false;

    // Create an array of mole numbers
    vector_fp molNum(nspecies,0.0);
    mphase->getMoles(molNum.data());

    // Other workspace
    vector_fp sm(ne*ne, 0.0);
    vector_fp ss(ne, 0.0);
    vector_fp sa(ne, 0.0);
    if (formRxnMatrix.size() < nspecies*ne) {
        formRxnMatrix.resize(nspecies*ne, 0.0);
    }

    // For debugging purposes keep an unmodified copy of the array.
    vector_fp molNumBase = molNum;
    double molSave = 0.0;
    size_t jr = 0;

    // Top of a loop of some sort based on the index JR. JR is the current
    // number of component species found.
    while (jr < nComponents) {
        // Top of another loop point based on finding a linearly independent
        // species
        size_t k = npos;
        while (true) {
            // Search the remaining part of the mole number vector, molNum for
            // the largest remaining species. Return its identity. kk is the raw
            // number. k is the orderVectorSpecies index.
            size_t kk = max_element(molNum.begin(), molNum.end()) - molNum.begin();
            size_t j;
            for (j = 0; j < nspecies; j++) {
                if (orderVectorSpecies[j] == kk) {
                    k = j;
                    break;
                }
            }
            if (j == nspecies) {
                throw CanteraError("BasisOptimize", "orderVectorSpecies contains an error");
            }

            if (molNum[kk] == 0.0) {
                *usedZeroedSpecies = true;
            }
            // If the largest molNum is negative, then we are done.
            if (molNum[kk] == USEDBEFORE) {
                nComponents = jr;
                nNonComponents = nspecies - nComponents;
                break;
            }

            // Assign a small negative number to the component that we have
            // just found, in order to take it out of further consideration.
            molSave = molNum[kk];
            molNum[kk] = USEDBEFORE;

            // CHECK LINEAR INDEPENDENCE WITH PREVIOUS SPECIES

            // Modified Gram-Schmidt Method, p. 202 Dalquist
            // QR factorization of a matrix without row pivoting.
            size_t jl = jr;
            for (j = 0; j < ne; ++j) {
                size_t jj = orderVectorElements[j];
                sm[j + jr*ne] = mphase->nAtoms(kk,jj);
            }
            if (jl > 0) {
                // Compute the coefficients of JA column of the the upper
                // triangular R matrix, SS(J) = R_J_JR (this is slightly
                // different than Dalquist) R_JA_JA = 1
                for (j = 0; j < jl; ++j) {
                    ss[j] = 0.0;
                    for (size_t i = 0; i < ne; ++i) {
                        ss[j] += sm[i + jr*ne] * sm[i + j*ne];
                    }
                    ss[j] /= sa[j];
                }

                // Now make the new column, (*,JR), orthogonal to the previous
                // columns
                for (j = 0; j < jl; ++j) {
                    for (size_t i = 0; i < ne; ++i) {
                        sm[i + jr*ne] -= ss[j] * sm[i + j*ne];
                    }
                }
            }

            // Find the new length of the new column in Q.
            // It will be used in the denominator in future row calcs.
            sa[jr] = 0.0;
            for (size_t ml = 0; ml < ne; ++ml) {
                double tmp = sm[ml + jr*ne];
                sa[jr] += tmp * tmp;
            }

            // IF NORM OF NEW ROW  .LT. 1E-3 REJECT
            if (sa[jr] > 1.0e-6) {
                break;
            }
        }

        // REARRANGE THE DATA
        if (jr != k) {
            if (BasisOptimize_print_lvl >= 1) {
                size_t kk = orderVectorSpecies[k];
                writelogf("   ---   %-12.12s", mphase->speciesName(kk));
                size_t jj = orderVectorSpecies[jr];
                writelogf("(%9.2g) replaces %-12.12s",
                          molSave, mphase->speciesName(jj));
                writelogf("(%9.2g) as component %3d\n", molNum[jj], jr);
            }
            std::swap(orderVectorSpecies[jr], orderVectorSpecies[k]);
        }

        // If we haven't found enough components, go back and find some more
        jr++;
    }

    if (! doFormRxn) {
        return nComponents;
    }

    // EVALUATE THE STOICHIOMETRY
    //
    // Formulate the matrix problem for the stoichiometric
    // coefficients. CX + B = 0
    //
    // C will be an nc x nc matrix made up of the formula vectors for the
    // components. Each component's formula vector is a column. The rows are the
    // elements.
    //
    // n RHS's will be solved for. Thus, B is an nc x n matrix.
    //
    // BIG PROBLEM 1/21/99:
    //
    // This algorithm makes the assumption that the first nc rows of the formula
    // matrix aren't rank deficient. However, this might not be the case. For
    // example, assume that the first element in FormulaMatrix[] is argon.
    // Assume that no species in the matrix problem actually includes argon.
    // Then, the first row in sm[], below will be identically zero. bleh.
    //
    // What needs to be done is to perform a rearrangement of the ELEMENTS ->
    // i.e. rearrange, FormulaMatrix, sp, and gai, such that the first nc
    // elements form in combination with the nc components create an invertible
    // sm[]. not a small project, but very doable.
    //
    // An alternative would be to turn the matrix problem below into an ne x nc
    // problem, and do QR elimination instead of Gauss-Jordan elimination.
    //
    // Note the rearrangement of elements need only be done once in the problem.
    // It's actually very similar to the top of this program with ne being the
    // species and nc being the elements!!
    for (size_t k = 0; k < nComponents; ++k) {
        size_t kk = orderVectorSpecies[k];
        for (size_t j = 0; j < nComponents; ++j) {
            size_t jj = orderVectorElements[j];
            sm[j + k*ne] = mphase->nAtoms(kk, jj);
        }
    }

    for (size_t i = 0; i < nNonComponents; ++i) {
        size_t k = nComponents + i;
        size_t kk = orderVectorSpecies[k];
        for (size_t j = 0; j < nComponents; ++j) {
            size_t jj = orderVectorElements[j];
            formRxnMatrix[j + i * ne] = - mphase->nAtoms(kk, jj);
        }
    }
    // Use LU factorization to calculate the reaction matrix
    int info;
    vector_int ipiv(nComponents);
    ct_dgetrf(nComponents, nComponents, &sm[0], ne, &ipiv[0], info);
    if (info) {
        throw CanteraError("BasisOptimize", "factorization returned an error condition");
    }
    ct_dgetrs(ctlapack::NoTranspose, nComponents, nNonComponents, &sm[0], ne,
              &ipiv[0], &formRxnMatrix[0], ne, info);

    if (BasisOptimize_print_lvl >= 1) {
        writelog("   ---\n");
        writelogf("   ---  Number of Components = %d\n", nComponents);
        writelog("   ---  Formula Matrix:\n");
        writelog("   ---                      Components:    ");
        for (size_t k = 0; k < nComponents; k++) {
            size_t kk = orderVectorSpecies[k];
            writelogf(" %3d (%3d) ", k, kk);
        }
        writelog("\n   ---                Components Moles:       ");
        for (size_t k = 0; k < nComponents; k++) {
            size_t kk = orderVectorSpecies[k];
            writelogf("%-11.3g", molNumBase[kk]);
        }
        writelog("\n   ---        NonComponent |   Moles  |       ");
        for (size_t i = 0; i < nComponents; i++) {
            size_t kk = orderVectorSpecies[i];
            writelogf("%-11.10s", mphase->speciesName(kk));
        }
        writelog("\n");

        for (size_t i = 0; i < nNonComponents; i++) {
            size_t k = i + nComponents;
            size_t kk = orderVectorSpecies[k];
            writelogf("   --- %3d (%3d) ", k, kk);
            writelogf("%-10.10s", mphase->speciesName(kk));
            writelogf("|%10.3g|", molNumBase[kk]);
            // Print the negative of formRxnMatrix[]; it's easier to interpret.
            for (size_t j = 0; j < nComponents; j++) {
                writelogf("     %6.2f", - formRxnMatrix[j + i * ne]);
            }
            writelog("\n");
        }
        writelog("   ");
        writeline('-', 77);
    }

    return nComponents;
} // basopt()