8 using namespace Cantera;
38 static size_t amax(
double* x,
size_t j,
size_t n);
63 static int mlequ(
double* c,
size_t idem,
size_t n,
double* b,
size_t m);
66 MultiPhase* mphase, std::vector<size_t>& orderVectorSpecies,
67 std::vector<size_t>& orderVectorElements,
70 size_t j, jj, k=0, kk, l, i, jl, ml;
81 size_t nspecies = mphase->
nSpecies();
83 doublereal
const USEDBEFORE = -1;
88 if (orderVectorElements.size() < ne) {
89 orderVectorElements.resize(ne);
90 for (j = 0; j < ne; j++) {
91 orderVectorElements[j] = j;
98 if (orderVectorSpecies.size() != nspecies) {
99 orderVectorSpecies.resize(nspecies);
100 for (k = 0; k < nspecies; k++) {
101 orderVectorSpecies[k] = k;
106 double molSave = 0.0;
109 for (i=0; i<77; i++) {
113 writelog(
" --- Subroutine BASOPT called to ");
114 writelog(
"calculate the number of components and ");
115 writelog(
"evaluate the formation matrix\n");
119 writelog(
" --- Formula Matrix used in BASOPT calculation\n");
120 writelog(
" --- Species | Order | ");
121 for (j = 0; j < ne; j++) {
122 jj = orderVectorElements[j];
129 for (k = 0; k < nspecies; k++) {
130 kk = orderVectorSpecies[k];
135 for (j = 0; j < ne; j++) {
136 jj = orderVectorElements[j];
137 double num = mphase->
nAtoms(kk,jj);
152 size_t nComponents = std::min(ne, nspecies);
153 size_t nNonComponents = nspecies - nComponents;
157 *usedZeroedSpecies =
false;
171 if (formRxnMatrix.size() < nspecies*ne) {
172 formRxnMatrix.resize(nspecies*ne, 0.0);
199 for (j = 0; j < nspecies; j++) {
200 if (orderVectorSpecies[j] == kk) {
206 throw CanteraError(
"BasisOptimize",
"orderVectorSpecies contains an error");
209 if (molNum[kk] == 0.0) {
210 *usedZeroedSpecies =
true;
215 if (molNum[kk] == USEDBEFORE) {
217 nNonComponents = nspecies - nComponents;
225 molSave = molNum[kk];
227 molNum[kk] = USEDBEFORE;
237 for (j = 0; j < ne; ++j) {
238 jj = orderVectorElements[j];
239 sm[j + jr*ne] = mphase->
nAtoms(kk,jj);
248 for (j = 0; j < jl; ++j) {
250 for (i = 0; i < ne; ++i) {
251 ss[j] += sm[i + jr*ne] * sm[i + j*ne];
259 for (j = 0; j < jl; ++j) {
260 for (l = 0; l < ne; ++l) {
261 sm[l + jr*ne] -= ss[j] * sm[l + j*ne];
270 for (ml = 0; ml < ne; ++ml) {
271 tmp = sm[ml + jr*ne];
277 if (sa[jr] < 1.0e-6) {
289 kk = orderVectorSpecies[k];
291 writelogf(
" --- %-12.12s", sname.c_str());
292 jj = orderVectorSpecies[jr];
294 writelogf(
"(%9.2g) replaces %-12.12s", molSave, ename.c_str());
295 writelogf(
"(%9.2g) as component %3d\n", molNum[jj], jr);
298 std::swap(orderVectorSpecies[jr], orderVectorSpecies[k]);
306 }
while (jr < (nComponents-1));
347 for (k = 0; k < nComponents; ++k) {
348 kk = orderVectorSpecies[k];
349 for (j = 0; j < nComponents; ++j) {
350 jj = orderVectorElements[j];
351 sm[j + k*ne] = mphase->
nAtoms(kk, jj);
355 for (i = 0; i < nNonComponents; ++i) {
357 kk = orderVectorSpecies[k];
358 for (j = 0; j < nComponents; ++j) {
359 jj = orderVectorElements[j];
360 formRxnMatrix[j + i * ne] = mphase->
nAtoms(kk, jj);
369 writelog(
"ERROR: mlequ returned an error condition\n");
370 throw CanteraError(
"basopt",
"mlequ returned an error condition");
376 writelogf(
" --- Number of Components = %d\n", nComponents);
379 for (k = 0; k < nComponents; k++) {
380 kk = orderVectorSpecies[k];
383 writelog(
"\n --- Components Moles: ");
384 for (k = 0; k < nComponents; k++) {
385 kk = orderVectorSpecies[k];
388 writelog(
"\n --- NonComponent | Moles | ");
389 for (i = 0; i < nComponents; i++) {
390 kk = orderVectorSpecies[i];
396 for (i = 0; i < nNonComponents; i++) {
398 kk = orderVectorSpecies[k];
406 for (j = 0; j < nComponents; j++) {
407 writelogf(
" %6.2f", - formRxnMatrix[j + i * ne]);
412 for (i=0; i<77; i++) {
442 int len = strlen(str);
443 if ((len) >= space) {
444 for (i = 0; i < space; i++) {
448 if (alignment == 1) {
450 }
else if (alignment == 2) {
453 ls = (space - len) / 2;
454 rs = space - len - ls;
457 for (i = 0; i < ls; i++) {
463 for (i = 0; i < rs; i++) {
480 static size_t amax(
double* x,
size_t j,
size_t n)
484 for (
size_t i = j + 1; i < n; ++i) {
493 static int mlequ(
double* c,
size_t idem,
size_t n,
double* b,
size_t m)
504 for (i = 0; i < n; ++i) {
505 if (c[i + i * idem] == 0.0) {
509 bool foundPivot =
false;
510 for (k = i + 1; k < n; ++k) {
511 if (c[k + i * idem] != 0.0) {
519 writelogf(
"vcs_mlequ ERROR: Encountered a zero column: %d\n", i);
524 for (j = 0; j < n; ++j) {
525 c[i + j * idem] += c[k + j * idem];
527 for (j = 0; j < m; ++j) {
528 b[i + j * idem] += b[k + j * idem];
532 for (l = 0; l < n; ++l) {
533 if (l != i && c[l + i * idem] != 0.0) {
534 R = c[l + i * idem] / c[i + i * idem];
535 c[l + i * idem] = 0.0;
536 for (j = i+1; j < n; ++j) {
537 c[l + j * idem] -= c[i + j * idem] * R;
539 for (j = 0; j < m; ++j) {
540 b[l + j * idem] -= b[i + j * idem] * R;
549 for (i = 0; i < n; ++i) {
550 for (j = 0; j < m; ++j) {
551 b[i + j * idem] = -b[i + j * idem] / c[i + i*idem];
559 std::vector<size_t>& orderVectorSpecies,
560 std::vector<size_t>& orderVectorElements)
562 size_t j, k, l, i, jl, ml, jr, ielem, jj, kk=0;
570 size_t nspecies = mphase->
nSpecies();
572 double test = -1.0E10;
576 for (i=0; i<77; i++) {
580 writelog(
" --- Subroutine ElemRearrange() called to ");
581 writelog(
"check stoich. coefficient matrix\n");
582 writelog(
" --- and to rearrange the element ordering once\n");
589 if (orderVectorElements.size() < nelements) {
590 orderVectorElements.resize(nelements);
591 for (j = 0; j < nelements; j++) {
592 orderVectorElements[j] = j;
601 if (orderVectorSpecies.size() != nspecies) {
602 orderVectorSpecies.resize(nspecies);
603 for (k = 0; k < nspecies; k++) {
604 orderVectorSpecies[k] = k;
615 if (elementAbundances.size() != nelements) {
616 for (j = 0; j < nelements; j++) {
618 for (k = 0; k < nspecies; k++) {
619 eAbund[j] += fabs(mphase->
nAtoms(k, j));
623 copy(elementAbundances.begin(), elementAbundances.end(),
650 for (ielem = jr; ielem < nelements; ielem++) {
651 kk = orderVectorElements[ielem];
652 if (eAbund[kk] != test && eAbund[kk] > 0.0) {
657 for (ielem = jr; ielem < nelements; ielem++) {
658 kk = orderVectorElements[ielem];
659 if (eAbund[kk] != test) {
665 if (k == nelements) {
671 writelogf(
"Error exit: returning with nComponents = %d\n", jr);
698 for (j = 0; j < nComponents; ++j) {
699 jj = orderVectorSpecies[j];
700 kk = orderVectorElements[k];
701 sm[j + jr*nComponents] = mphase->
nAtoms(jj,kk);
710 for (j = 0; j < jl; ++j) {
712 for (i = 0; i < nComponents; ++i) {
713 ss[j] += sm[i + jr*nComponents] * sm[i + j*nComponents];
721 for (j = 0; j < jl; ++j) {
722 for (l = 0; l < nComponents; ++l) {
723 sm[l + jr*nComponents] -= ss[j] * sm[l + j*nComponents];
733 for (ml = 0; ml < nComponents; ++ml) {
734 double tmp = sm[ml + jr*nComponents];
740 if (sa[jr] < 1.0e-6) {
752 kk = orderVectorElements[k];
757 kk = orderVectorElements[jr];
763 std::swap(orderVectorElements[jr], orderVectorElements[k]);
771 }
while (jr < (nComponents-1));
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.
int BasisOptimize_print_lvl
External int that is used to turn on debug printing for the BasisOptimze program. ...
const size_t npos
index returned by functions to indicate "no position"
std::string speciesName(const size_t kGlob) const
Name of species with global index kGlob.
Headers for the MultiPhase object that is used to set up multiphase equilibrium problems (see Equilib...
A class for multiphase mixtures.
void writelogf(const char *fmt,...)
Write a formatted message to the screen.
std::string elementName(size_t m) const
Returns the name of the global element m.
static int mlequ(double *c, size_t idem, size_t n, double *b, size_t m)
Invert an nxn matrix and solve m rhs's.
Base class for exceptions thrown by Cantera classes.
void getMoles(doublereal *molNum) const
Get the mole numbers of all species in the multiphase object.
doublereal nAtoms(const size_t kGlob, const size_t mGlob) const
Returns the Number of atoms of global element mGlob in global species kGlob.
static size_t amax(double *x, size_t j, size_t n)
Finds the location of the maximum component in a vector x
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
#define DATA_PTR(vec)
Creates a pointer to the start of the raw data for a vector.
static void print_stringTrunc(const char *str, int space, int alignment)
Print a string within a given space limit.
void writelog(const std::string &msg)
Write a message to the screen.
size_t nSpecies() const
Number of species, summed over all phases.
Header file for class ThermoPhase, the base class for phases with thermodynamic properties, and the text for the Module thermoprops (see Thermodynamic Properties and class ThermoPhase).
size_t 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...
size_t nElements() const
Number of elements.