void MMCollisionInt::fit(int degree, doublereal deltastar, doublereal* a, doublereal* b, doublereal* c) { int i, n = m_nmax - m_nmin + 1; int ndeg=0; vector_fp values(n); doublereal rmserr; vector_fp w(n); doublereal* logT = DATA_PTR(m_logTemp) + m_nmin; for (i = 0; i < n; i++) { if (deltastar == 0.0) { values[i] = astar_table[8*(i + m_nmin + 1)]; } else { values[i] = poly5(deltastar, DATA_PTR(m_apoly[i+m_nmin])); } } w[0]= -1.0; rmserr = polyfit(n, logT, DATA_PTR(values), DATA_PTR(w), degree, ndeg, 0.0, a); for (i = 0; i < n; i++) { if (deltastar == 0.0) { values[i] = bstar_table[8*(i + m_nmin + 1)]; } else { values[i] = poly5(deltastar, DATA_PTR(m_bpoly[i+m_nmin])); } } w[0]= -1.0; rmserr = polyfit(n, logT, DATA_PTR(values), DATA_PTR(w), degree, ndeg, 0.0, b); for (i = 0; i < n; i++) { if (deltastar == 0.0) { values[i] = cstar_table[8*(i + m_nmin + 1)]; } else { values[i] = poly5(deltastar, DATA_PTR(m_cpoly[i+m_nmin])); } } w[0]= -1.0; rmserr = polyfit(n, logT, DATA_PTR(values), DATA_PTR(w), degree, ndeg, 0.0, c); if (DEBUG_MODE_ENABLED && m_loglevel > 2) { writelogf("\nT* fit at delta* = %.6g\n", deltastar); writelog("astar = [" + vec2str(vector_fp(a, a+degree+1))+ "]\n"); if (rmserr > 0.01) { writelogf("Warning: RMS error = %12.6g for A* fit\n", rmserr); } writelog("bstar = [" + vec2str(vector_fp(b, b+degree+1))+ "]\n"); if (rmserr > 0.01) { writelogf("Warning: RMS error = %12.6g for B* fit\n", rmserr); } writelog("cstar = [" + vec2str(vector_fp(c, c+degree+1))+ "]\n"); if (rmserr > 0.01) { writelogf("Warning: RMS error = %12.6g for C* fit\n", rmserr); } } }
//==================================================================================================================== int invert(DenseMatrix& A, size_t nn) { integer n = static_cast<int>(nn != npos ? nn : A.nRows()); int info=0; ct_dgetrf(n, n, A.ptrColumn(0), static_cast<int>(A.nRows()), &A.ipiv()[0], info); if (info != 0) { if (A.m_printLevel) { writelogf("invert(DenseMatrix& A, int nn): DGETRS returned INFO = %d\n", info); } if (! A.m_useReturnErrorCode) { throw CELapackError("invert(DenseMatrix& A, int nn)", "DGETRS returned INFO = "+int2str(info)); } return info; } vector_fp work(n); integer lwork = static_cast<int>(work.size()); ct_dgetri(n, A.ptrColumn(0), static_cast<int>(A.nRows()), &A.ipiv()[0], &work[0], lwork, info); if (info != 0) { if (A.m_printLevel) { writelogf("invert(DenseMatrix& A, int nn): DGETRS returned INFO = %d\n", info); } if (! A.m_useReturnErrorCode) { throw CELapackError("invert(DenseMatrix& A, int nn)", "DGETRI returned INFO="+int2str(info)); } } return info; }
/* * This is the main routine that reads a ctml file and puts it into * an XML_Node tree * * @param node Root of the tree * @param file Name of the file * @param debug Turn on debugging printing */ void get_CTML_Tree(Cantera::XML_Node* rootPtr, const std::string file, const int debug) { std::string ff, ext = ""; // find the input file on the Cantera search path std::string inname = findInputFile(file); #ifdef DEBUG_PATHS writelog("Found file: "+inname+"\n"); #endif if (debug > 0) writelog("Found file: "+inname+"\n"); if (inname == "") { throw CanteraError("get_CTML_Tree", "file "+file+" not found"); } /* * Check whether or not the file is XML. If not, it will be first * processed with the preprocessor. */ std::string::size_type idot = inname.rfind('.'); if (idot != string::npos) { ext = inname.substr(idot, inname.size()); } if (ext != ".xml" && ext != ".ctml") { try { ctml::ct2ctml(inname.c_str(), debug); } catch (...) { writelog("get_CTML_Tree: caught something \n");; } string ffull = inname.substr(0,idot) + ".xml"; ff = "./" + getBaseName(ffull) + ".xml"; #ifdef DEBUG_PATHS writelogf("ffull name = %s\n", ffull.c_str()); writelogf("ff name = %s\n", ff.c_str()); #endif } else { ff = inname; } #ifdef DEBUG_PATHS writelog("Attempting to parse xml file " + ff + "\n"); #else if (debug > 0) writelog("Attempting to parse xml file " + ff + "\n"); #endif ifstream fin(ff.c_str()); if (!fin) { throw CanteraError("get_CTML_Tree", "XML file " + ff + " not found"); } rootPtr->build(fin); fin.close(); }
//==================================================================================================================== 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; }
/* * Solve Ax = b. Vector b is overwritten on exit with x. */ int SquareMatrix::solveQR(doublereal * b) { int info=0; /* * Check to see whether the matrix has been factored. */ if (!m_factored) { int retn = factorQR(); if (retn) { return retn; } } int lwork = work.size(); if (lwork < m_nrows) { work.resize(8 * m_nrows, 0.0); lwork = 8 * m_nrows; } /* * Solve the factored system */ ct_dormqr(ctlapack::Left, ctlapack::Transpose, m_nrows, 1, m_nrows, &(*(begin())), m_nrows, DATA_PTR(tau), b, m_nrows, DATA_PTR(work), lwork, info); if (info != 0) { if (m_printLevel) { writelogf("SquareMatrix::solveQR(): DORMQR returned INFO = %d\n", info); } if (! m_useReturnErrorCode) { throw CELapackError("SquareMatrix::solveQR()", "DORMQR returned INFO = " + int2str(info)); } } int lworkOpt = work[0]; if (lworkOpt > lwork) { work.resize(lworkOpt); } char dd = 'N'; ct_dtrtrs(ctlapack::UpperTriangular, ctlapack::NoTranspose, &dd, m_nrows, 1, &(*(begin())), m_nrows, b, m_nrows, info); if (info != 0) { if (m_printLevel) { writelogf("SquareMatrix::solveQR(): DTRTRS returned INFO = %d\n", info); } if (! m_useReturnErrorCode) { throw CELapackError("SquareMatrix::solveQR()", "DTRTRS returned INFO = " + int2str(info)); } } return info; }
doublereal BandMatrix::rcond(doublereal a1norm) { int printLevel = 0; int useReturnErrorCode = 0; if (iwork_.size() < m_n) { iwork_.resize(m_n); } if (work_.size() < 3 * m_n) { work_.resize(3 * m_n); } doublereal rcond = 0.0; if (m_factored != 1) { throw CanteraError("BandMatrix::rcond()", "matrix isn't factored correctly"); } size_t ldab = (2 *m_kl + m_ku + 1); int rinfo = 0; rcond = ct_dgbcon('1', m_n, m_kl, m_ku, ludata.data(), ldab, m_ipiv.data(), a1norm, work_.data(), iwork_.data(), rinfo); if (rinfo != 0) { if (printLevel) { writelogf("BandMatrix::rcond(): DGBCON returned INFO = %d\n", rinfo); } if (! useReturnErrorCode) { throw CanteraError("BandMatrix::rcond()", "DGBCON returned INFO = {}", rinfo); } } return rcond; }
/* * 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; }
//===================================================================================================================== doublereal SquareMatrix::rcondQR() { if ((int) iwork_.size() < m_nrows) { iwork_.resize(m_nrows); } if ((int) work.size() <3 * m_nrows) { work.resize(3 * m_nrows); } doublereal rcond = 0.0; if (m_factored != 2) { throw CELapackError("SquareMatrix::rcondQR()", "matrix isn't factored correctly"); } int rinfo; rcond = ct_dtrcon(0, ctlapack::UpperTriangular, 0, m_nrows, &(*(begin())), m_nrows, DATA_PTR(work), DATA_PTR(iwork_), rinfo); if (rinfo != 0) { if (m_printLevel) { writelogf("SquareMatrix::rcondQR(): DTRCON returned INFO = %d\n", rinfo); } if (! m_useReturnErrorCode) { throw CELapackError("SquareMatrix::rcondQR()", "DTRCON returned INFO = " + int2str(rinfo)); } } return rcond; }
//===================================================================================================================== doublereal SquareMatrix::rcond(doublereal anorm) { if ((int) iwork_.size() < m_nrows) { iwork_.resize(m_nrows); } if ((int) work.size() <4 * m_nrows) { work.resize(4 * m_nrows); } doublereal rcond = 0.0; if (m_factored != 1) { throw CELapackError("SquareMatrix::rcond()", "matrix isn't factored correctly"); } // doublereal anorm = ct_dlange('1', m_nrows, m_nrows, &(*(begin())), m_nrows, DATA_PTR(work)); int rinfo; rcond = ct_dgecon('1', m_nrows, &(*(begin())), m_nrows, anorm, DATA_PTR(work), DATA_PTR(iwork_), rinfo); if (rinfo != 0) { if (m_printLevel) { writelogf("SquareMatrix::rcond(): DGECON returned INFO = %d\n", rinfo); } if (! m_useReturnErrorCode) { throw CELapackError("SquareMatrix::rcond()", "DGECON returned INFO = " + int2str(rinfo)); } } return rcond; }
//===================================================================================================================== int SquareMatrix::factorQR() { if ((int) tau.size() < m_nrows) { tau.resize(m_nrows, 0.0); work.resize(8 * m_nrows, 0.0); } a1norm_ = ct_dlange('1', m_nrows, m_nrows, &(*(begin())), m_nrows, DATA_PTR(work)); int info; m_factored = 2; int lwork = work.size(); ct_dgeqrf(m_nrows, m_nrows, &(*(begin())), m_nrows, DATA_PTR(tau), DATA_PTR(work), lwork, info); if (info != 0) { if (m_printLevel) { writelogf("SquareMatrix::factorQR(): DGEQRF returned INFO = %d\n", info); } if (! m_useReturnErrorCode) { throw CELapackError("SquareMatrix::factorQR()", "DGEQRF returned INFO = " + int2str(info)); } } int lworkOpt = work[0]; if (lworkOpt > lwork) { work.resize(lworkOpt); } return info; }
/* * Factor A. A is overwritten with the LU decomposition of A. */ int SquareMatrix::factor() { if (useQR_) { return factorQR(); } a1norm_ = ct_dlange('1', m_nrows, m_nrows, &(*(begin())), m_nrows, DATA_PTR(work)); integer n = static_cast<int>(nRows()); int info=0; m_factored = 1; ct_dgetrf(n, n, &(*(begin())), static_cast<int>(nRows()), DATA_PTR(ipiv()), info); if (info != 0) { if (m_printLevel) { writelogf("SquareMatrix::factor(): DGETRS returned INFO = %d\n", info); } if (! m_useReturnErrorCode) { throw CELapackError("SquareMatrix::factor()", "DGETRS returned INFO = "+int2str(info)); } } return info; }
void MMCollisionInt::fit_omega22(int degree, doublereal deltastar, doublereal* o22) { int i, n = m_nmax - m_nmin + 1; int ndeg=0; vector_fp values(n); doublereal rmserr; vector_fp w(n); doublereal* logT = DATA_PTR(m_logTemp) + m_nmin; for (i = 0; i < n; i++) { if (deltastar == 0.0) { values[i] = omega22_table[8*(i + m_nmin)]; } else { values[i] = poly5(deltastar, DATA_PTR(m_o22poly[i+m_nmin])); } } w[0]= -1.0; rmserr = polyfit(n, logT, DATA_PTR(values), DATA_PTR(w), degree, ndeg, 0.0, o22); if (DEBUG_MODE_ENABLED && m_loglevel > 0 && rmserr > 0.01) { writelogf("Warning: RMS error = %12.6g in omega_22 fit" "with delta* = %12.6g\n", rmserr, deltastar); } }
/** @todo fix lwork */ int leastSquares(DenseMatrix& A, double* b) { int info = 0; int rank = 0; double rcond = -1.0; // fix this! int lwork = 6000; // 2*(3*min(m,n) + max(2*min(m,n), max(m,n))); vector_fp work(lwork); vector_fp s(min(static_cast<int>(A.nRows()), static_cast<int>(A.nColumns()))); ct_dgelss(static_cast<int>(A.nRows()), static_cast<int>(A.nColumns()), 1, A.ptrColumn(0), static_cast<int>(A.nRows()), b, static_cast<int>(A.nColumns()), &s[0], //.begin(), rcond, rank, &work[0], work.size(), info); if (info != 0) { if (A.m_printLevel) { writelogf("leastSquares(): DGELSS returned INFO = %d\n", info); } if (! A.m_useReturnErrorCode) { throw CELapackError("leastSquares()", "DGELSS returned INFO = " + int2str(info)); } } return info; }
void ElemRearrange(size_t nComponents, const vector_fp& elementAbundances, MultiPhase* mphase, std::vector<size_t>& orderVectorSpecies, std::vector<size_t>& orderVectorElements) { size_t nelements = mphase->nElements(); // Get the total number of species in the multiphase object size_t nspecies = mphase->nSpecies(); if (BasisOptimize_print_lvl > 0) { writelog(" "); writeline('-', 77); writelog(" --- Subroutine ElemRearrange() called to "); writelog("check stoich. coefficient matrix\n"); writelog(" --- and to rearrange the element ordering once\n"); } // Perhaps, initialize the element ordering if (orderVectorElements.size() < nelements) { orderVectorElements.resize(nelements); for (size_t j = 0; j < nelements; j++) { orderVectorElements[j] = j; } } // Perhaps, initialize the species ordering. However, this is dangerous, as // this ordering is assumed to yield the component species for the problem if (orderVectorSpecies.size() != nspecies) { orderVectorSpecies.resize(nspecies); for (size_t k = 0; k < nspecies; k++) { orderVectorSpecies[k] = k; } } // If the elementAbundances aren't input, just create a fake one based on // summing the column of the stoich matrix. This will force elements with // zero species to the end of the element ordering. vector_fp eAbund(nelements,0.0); if (elementAbundances.size() != nelements) { for (size_t j = 0; j < nelements; j++) { eAbund[j] = 0.0; for (size_t k = 0; k < nspecies; k++) { eAbund[j] += fabs(mphase->nAtoms(k, j)); } } } else { copy(elementAbundances.begin(), elementAbundances.end(), eAbund.begin()); } vector_fp sa(nelements,0.0); vector_fp ss(nelements,0.0); vector_fp sm(nelements*nelements,0.0); // Top of a loop of some sort based on the index JR. JR is the current // number independent elements found. size_t jr = 0; while (jr < nComponents) { // Top of another loop point based on finding a linearly independent // element size_t k = nelements; while (true) { // Search the element vector. We first locate elements that are // present in any amount. Then, we locate elements that are not // present in any amount. Return its identity in K. size_t kk; for (size_t ielem = jr; ielem < nelements; ielem++) { kk = orderVectorElements[ielem]; if (eAbund[kk] != USEDBEFORE && eAbund[kk] > 0.0) { k = ielem; break; } } for (size_t ielem = jr; ielem < nelements; ielem++) { kk = orderVectorElements[ielem]; if (eAbund[kk] != USEDBEFORE) { k = ielem; break; } } if (k == nelements) { // When we are here, there is an error usually. // We haven't found the number of elements necessary. if (BasisOptimize_print_lvl > 0) { writelogf("Error exit: returning with nComponents = %d\n", jr); } throw CanteraError("ElemRearrange", "Required number of elements not found."); } // Assign a large negative number to the element that we have // just found, in order to take it out of further consideration. eAbund[kk] = USEDBEFORE; // CHECK LINEAR INDEPENDENCE OF CURRENT FORMULA MATRIX // LINE WITH PREVIOUS LINES OF THE FORMULA MATRIX // Modified Gram-Schmidt Method, p. 202 Dalquist // QR factorization of a matrix without row pivoting. size_t jl = jr; // Fill in the row for the current element, k, under consideration // The row will contain the Formula matrix value for that element // with respect to the vector of component species. (note j and k // indices are flipped compared to the previous routine) for (size_t j = 0; j < nComponents; ++j) { size_t jj = orderVectorSpecies[j]; kk = orderVectorElements[k]; sm[j + jr*nComponents] = mphase->nAtoms(jj,kk); } 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 (size_t j = 0; j < jl; ++j) { ss[j] = 0.0; for (size_t i = 0; i < nComponents; ++i) { ss[j] += sm[i + jr*nComponents] * sm[i + j*nComponents]; } ss[j] /= sa[j]; } // Now make the new column, (*,JR), orthogonal to the // previous columns for (size_t j = 0; j < jl; ++j) { for (size_t i = 0; i < nComponents; ++i) { sm[i + jr*nComponents] -= ss[j] * sm[i + j*nComponents]; } } } // 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 < nComponents; ++ml) { double tmp = sm[ml + jr*nComponents]; sa[jr] += tmp * tmp; } // IF NORM OF NEW ROW .LT. 1E-6 REJECT if (sa[jr] > 1.0e-6) { break; } } // REARRANGE THE DATA if (jr != k) { if (BasisOptimize_print_lvl > 0) { size_t kk = orderVectorElements[k]; writelog(" --- "); writelogf("%-2.2s", mphase->elementName(kk)); writelog("replaces "); kk = orderVectorElements[jr]; writelogf("%-2.2s", mphase->elementName(kk)); writelogf(" as element %3d\n", jr); } std::swap(orderVectorElements[jr], orderVectorElements[k]); } // If we haven't found enough components, go back and find some more jr++; }; }
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()
void MMCollisionInt::init(doublereal tsmin, doublereal tsmax, int log_level) { m_loglevel = log_level; if (DEBUG_MODE_ENABLED && m_loglevel > 0) { writelog("Collision Integral Polynomial Fits\n"); } m_nmin = -1; m_nmax = -1; for (int n = 0; n < 37; n++) { if (tsmin > tstar[n+1]) { m_nmin = n; } if (tsmax > tstar[n+1]) { m_nmax = n+1; } } if (m_nmin < 0 || m_nmin >= 36 || m_nmax < 0 || m_nmax > 36) { m_nmin = 0; m_nmax = 36; } if (DEBUG_MODE_ENABLED && m_loglevel > 0) { writelogf("T*_min = %g\n", tstar[m_nmin + 1]); writelogf("T*_max = %g\n", tstar[m_nmax + 1]); } m_logTemp.resize(37); doublereal rmserr, e22 = 0.0, ea = 0.0, eb = 0.0, ec = 0.0; if (DEBUG_MODE_ENABLED && m_loglevel > 0) { writelog("Collision integral fits at each tabulated T* vs. delta*.\n" "These polynomial fits are used to interpolate between " "columns (delta*)\n in the Monchick and Mason tables." " They are only used for nonzero delta*.\n"); if (log_level < 4) { writelog("polynomial coefficients not printed (log_level < 4)\n"); } } for (int i = 0; i < 37; i++) { m_logTemp[i] = log(tstar[i+1]); vector_fp c(DeltaDegree+1); rmserr = fitDelta(0, i, DeltaDegree, DATA_PTR(c)); if (DEBUG_MODE_ENABLED && log_level > 3) { writelogf("\ndelta* fit at T* = %.6g\n", tstar[i+1]); writelog("omega22 = [" + vec2str(c) + "]\n"); } m_o22poly.push_back(c); e22 = std::max(e22, rmserr); rmserr = fitDelta(1, i, DeltaDegree, DATA_PTR(c)); m_apoly.push_back(c); if (DEBUG_MODE_ENABLED && log_level > 3) { writelog("A* = [" + vec2str(c) + "]\n"); } ea = std::max(ea, rmserr); rmserr = fitDelta(2, i, DeltaDegree, DATA_PTR(c)); m_bpoly.push_back(c); if (DEBUG_MODE_ENABLED && log_level > 3) { writelog("B* = [" + vec2str(c) + "]\n"); } eb = std::max(eb, rmserr); rmserr = fitDelta(3, i, DeltaDegree, DATA_PTR(c)); m_cpoly.push_back(c); if (DEBUG_MODE_ENABLED && log_level > 3) { writelog("C* = [" + vec2str(c) + "]\n"); } ec = std::max(ec, rmserr); if (DEBUG_MODE_ENABLED && log_level > 0) { writelogf("max RMS errors in fits vs. delta*:\n" " omega_22 = %12.6g \n" " A* = %12.6g \n" " B* = %12.6g \n" " C* = %12.6g \n", e22, ea, eb, ec); } } }