16 static const double USEDBEFORE = -1;
19 std::vector<size_t>& orderVectorSpecies,
20 std::vector<size_t>& orderVectorElements,
27 size_t nspecies = mphase->
nSpecies();
30 if (orderVectorElements.size() < ne) {
31 orderVectorElements.resize(ne);
32 iota(orderVectorElements.begin(), orderVectorElements.end(), 0);
36 if (orderVectorSpecies.size() != nspecies) {
37 orderVectorSpecies.resize(nspecies);
38 iota(orderVectorSpecies.begin(), orderVectorSpecies.end(), 0);
44 writelog(
" --- Subroutine BASOPT called to ");
45 writelog(
"calculate the number of components and ");
46 writelog(
"evaluate the formation matrix\n");
50 writelog(
" --- Formula Matrix used in BASOPT calculation\n");
52 for (
size_t j = 0; j < ne; j++) {
53 size_t jj = orderVectorElements[j];
57 for (
size_t k = 0; k < nspecies; k++) {
58 size_t kk = orderVectorSpecies[k];
59 writelog(
" --- {:>11.11s} | {:4d} |",
61 for (
size_t j = 0; j < ne; j++) {
62 size_t jj = orderVectorElements[j];
63 double num = mphase->
nAtoms(kk,jj);
75 size_t nComponents = std::min(ne, nspecies);
76 size_t nNonComponents = nspecies - nComponents;
79 *usedZeroedSpecies =
false;
89 if (formRxnMatrix.size() < nspecies*ne) {
90 formRxnMatrix.resize(nspecies*ne, 0.0);
100 while (jr < nComponents) {
108 size_t kk = max_element(molNum.begin(), molNum.end()) - molNum.begin();
110 for (j = 0; j < nspecies; j++) {
111 if (orderVectorSpecies[j] == kk) {
117 throw CanteraError(
"BasisOptimize",
"orderVectorSpecies contains an error");
120 if (molNum[kk] == 0.0) {
121 *usedZeroedSpecies =
true;
124 if (molNum[kk] == USEDBEFORE) {
126 nNonComponents = nspecies - nComponents;
132 molSave = molNum[kk];
133 molNum[kk] = USEDBEFORE;
140 for (j = 0; j < ne; ++j) {
141 size_t jj = orderVectorElements[j];
142 sm(j, jr) = mphase->
nAtoms(kk,jj);
148 for (j = 0; j < jl; ++j) {
150 for (
size_t i = 0; i < ne; ++i) {
151 ss[j] += sm(i, jr) * sm(i, j);
158 for (j = 0; j < jl; ++j) {
159 for (
size_t i = 0; i < ne; ++i) {
160 sm(i, jr) -= ss[j] * sm(i, j);
168 for (
size_t ml = 0; ml < ne; ++ml) {
169 sa[jr] += pow(sm(ml, jr), 2);
173 if (sa[jr] > 1.0e-6) {
181 size_t kk = orderVectorSpecies[k];
183 size_t jj = orderVectorSpecies[jr];
186 writelogf(
"(%9.2g) as component %3d\n", molNum[jj], jr);
188 std::swap(orderVectorSpecies[jr], orderVectorSpecies[k]);
230 sm.
resize(nComponents, nComponents);
231 for (
size_t k = 0; k < nComponents; ++k) {
232 size_t kk = orderVectorSpecies[k];
233 for (
size_t j = 0; j < nComponents; ++j) {
234 size_t jj = orderVectorElements[j];
235 sm(j, k) = mphase->
nAtoms(kk, jj);
239 for (
size_t i = 0; i < nNonComponents; ++i) {
240 size_t k = nComponents + i;
241 size_t kk = orderVectorSpecies[k];
242 for (
size_t j = 0; j < nComponents; ++j) {
243 size_t jj = orderVectorElements[j];
244 formRxnMatrix[j + i * ne] = - mphase->
nAtoms(kk, jj);
249 solve(sm, formRxnMatrix.
data(), nNonComponents, ne);
253 writelogf(
" --- Number of Components = %d\n", nComponents);
256 for (
size_t k = 0; k < nComponents; k++) {
257 size_t kk = orderVectorSpecies[k];
260 writelog(
"\n --- Components Moles: ");
261 for (
size_t k = 0; k < nComponents; k++) {
262 size_t kk = orderVectorSpecies[k];
265 writelog(
"\n --- NonComponent | Moles | ");
266 for (
size_t i = 0; i < nComponents; i++) {
267 size_t kk = orderVectorSpecies[i];
272 for (
size_t i = 0; i < nNonComponents; i++) {
273 size_t k = i + nComponents;
274 size_t kk = orderVectorSpecies[k];
279 for (
size_t j = 0; j < nComponents; j++) {
280 writelogf(
" %6.2f", - formRxnMatrix[j + i * ne]);
294 std::vector<size_t>& orderVectorSpecies,
295 std::vector<size_t>& orderVectorElements)
299 size_t nspecies = mphase->
nSpecies();
304 writelog(
" --- Subroutine ElemRearrange() called to ");
305 writelog(
"check stoich. coefficient matrix\n");
306 writelog(
" --- and to rearrange the element ordering once\n");
310 if (orderVectorElements.size() < nelements) {
311 orderVectorElements.resize(nelements);
312 for (
size_t j = 0; j < nelements; j++) {
313 orderVectorElements[j] = j;
319 if (orderVectorSpecies.size() != nspecies) {
320 orderVectorSpecies.resize(nspecies);
321 for (
size_t k = 0; k < nspecies; k++) {
322 orderVectorSpecies[k] = k;
330 if (elementAbundances.size() != nelements) {
331 for (
size_t j = 0; j < nelements; j++) {
333 for (
size_t k = 0; k < nspecies; k++) {
334 eAbund[j] += fabs(mphase->
nAtoms(k, j));
338 copy(elementAbundances.begin(), elementAbundances.end(),
349 while (jr < nComponents) {
352 size_t k = nelements;
359 for (
size_t ielem = jr; ielem < nelements; ielem++) {
360 kk = orderVectorElements[ielem];
361 if (eAbund[kk] != USEDBEFORE && eAbund[kk] > 0.0) {
366 for (
size_t ielem = jr; ielem < nelements; ielem++) {
367 kk = orderVectorElements[ielem];
368 if (eAbund[kk] != USEDBEFORE) {
374 if (k == nelements) {
378 writelogf(
"Error exit: returning with nComponents = %d\n", jr);
380 throw CanteraError(
"ElemRearrange",
"Required number of elements not found.");
385 eAbund[kk] = USEDBEFORE;
398 for (
size_t j = 0; j < nComponents; ++j) {
399 size_t jj = orderVectorSpecies[j];
400 kk = orderVectorElements[k];
401 sm[j + jr*nComponents] = mphase->
nAtoms(jj,kk);
407 for (
size_t j = 0; j < jl; ++j) {
409 for (
size_t i = 0; i < nComponents; ++i) {
410 ss[j] += sm[i + jr*nComponents] * sm[i + j*nComponents];
417 for (
size_t j = 0; j < jl; ++j) {
418 for (
size_t i = 0; i < nComponents; ++i) {
419 sm[i + jr*nComponents] -= ss[j] * sm[i + j*nComponents];
427 for (
size_t ml = 0; ml < nComponents; ++ml) {
428 double tmp = sm[ml + jr*nComponents];
432 if (sa[jr] > 1.0e-6) {
439 size_t kk = orderVectorElements[k];
443 kk = orderVectorElements[jr];
447 std::swap(orderVectorElements[jr], orderVectorElements[k]);
Headers for the MultiPhase object that is used to set up multiphase equilibrium problems (see Equilfu...
vector_fp & data()
Return a reference to the data vector.
Base class for exceptions thrown by Cantera classes.
A class for full (non-sparse) matrices with Fortran-compatible data storage, which adds matrix operat...
void resize(size_t n, size_t m, doublereal v=0.0)
Resize the matrix.
A class for multiphase mixtures.
void getMoles(doublereal *molNum) const
Get the mole numbers of all species in the multiphase object.
size_t nSpecies() const
Number of species, summed over all phases.
std::string speciesName(const size_t kGlob) const
Name of species with global index kGlob.
std::string elementName(size_t m) const
Returns the name of the global element m.
doublereal nAtoms(const size_t kGlob, const size_t mGlob) const
Returns the Number of atoms of global element mGlob in global species kGlob.
size_t nElements() const
Number of elements.
size_t BasisOptimize(int *usedZeroedSpecies, bool doFormRxn, MultiPhase *mphase, std::vector< size_t > &orderVectorSpecies, std::vector< size_t > &orderVectorElements, vector_fp &formRxnMatrix)
Choose the optimum basis of species for the equilibrium calculations.
void ElemRearrange(size_t nComponents, const vector_fp &elementAbundances, MultiPhase *mphase, std::vector< size_t > &orderVectorSpecies, std::vector< size_t > &orderVectorElements)
Handles the potential rearrangement of the constraint equations represented by the Formula Matrix.
const size_t npos
index returned by functions to indicate "no position"
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
void writelog(const std::string &fmt, const Args &... args)
Write a formatted message to the screen.
void writelogf(const char *fmt, const Args &... args)
Write a formatted message to the screen.
Namespace for the Cantera kernel.
int BasisOptimize_print_lvl
External int that is used to turn on debug printing for the BasisOptimze program.
int solve(DenseMatrix &A, double *b, size_t nrhs, size_t ldb)
Solve Ax = b. Array b is overwritten on exit with x.