示例#1
0
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);
        }
    }
}
示例#2
0
//====================================================================================================================
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;
}
示例#3
0
  /*
   *  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();
  }
示例#4
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;
  }
示例#5
0
  /*
   * 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;
  }
示例#6
0
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;
}
示例#7
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;
  }
示例#8
0
  //=====================================================================================================================
  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;
  }
示例#9
0
  //=====================================================================================================================
  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;
  }
示例#10
0
  //=====================================================================================================================
  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;
  }
示例#11
0
  /*
   * 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;
  }
示例#12
0
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);
    }
}
示例#13
0
  /** @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; 
  }
示例#14
0
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++;
    };
}
示例#15
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()
示例#16
0
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);
        }
    }
}