13 using namespace Cantera;
19 int BasisOptimize_print_lvl = 0;
32 static void print_stringTrunc(
const char* str,
int space,
int alignment);
44 static size_t amax(
double* x,
size_t j,
size_t n);
74 static int mlequ(
double* c,
size_t idem,
size_t n,
double* b,
size_t m);
122 MultiPhase* mphase, std::vector<size_t>& orderVectorSpecies,
123 std::vector<size_t>& orderVectorElements,
127 size_t j, jj, k=0, kk, l, i, jl, ml;
138 size_t nspecies = mphase->
nSpecies();
140 doublereal
const USEDBEFORE = -1;
145 if (orderVectorElements.size() < ne) {
146 orderVectorElements.resize(ne);
147 for (j = 0; j < ne; j++) {
148 orderVectorElements[j] = j;
155 if (orderVectorSpecies.size() != nspecies) {
156 orderVectorSpecies.resize(nspecies);
157 for (k = 0; k < nspecies; k++) {
158 orderVectorSpecies[k] = k;
163 double molSave = 0.0;
164 if (BasisOptimize_print_lvl >= 1) {
166 for (i=0; i<77; i++) {
170 writelog(
" --- Subroutine BASOPT called to ");
171 writelog(
"calculate the number of components and ");
172 writelog(
"evaluate the formation matrix\n");
173 if (BasisOptimize_print_lvl > 0) {
176 writelog(
" --- Formula Matrix used in BASOPT calculation\n");
177 writelog(
" --- Species | Order | ");
178 for (j = 0; j < ne; j++) {
179 jj = orderVectorElements[j];
182 print_stringTrunc(ename.c_str(), 4, 1);
186 for (k = 0; k < nspecies; k++) {
187 kk = orderVectorSpecies[k];
190 print_stringTrunc(sname.c_str(), 11, 1);
192 for (j = 0; j < ne; j++) {
193 jj = orderVectorElements[j];
194 double num = mphase->
nAtoms(kk,jj);
209 size_t nComponents =
std::min(ne, nspecies);
210 size_t nNonComponents = nspecies - nComponents;
214 *usedZeroedSpecies =
false;
228 if (formRxnMatrix.size() < nspecies*ne) {
229 formRxnMatrix.resize(nspecies*ne, 0.0);
256 for (j = 0; j < nspecies; j++) {
257 if (orderVectorSpecies[j] == kk) {
263 throw CanteraError(
"BasisOptimize",
"orderVectorSpecies contains an error");
266 if (molNum[kk] == 0.0) {
267 *usedZeroedSpecies =
true;
272 if (molNum[kk] == USEDBEFORE) {
274 nNonComponents = nspecies - nComponents;
282 molSave = molNum[kk];
284 molNum[kk] = USEDBEFORE;
294 for (j = 0; j < ne; ++j) {
295 jj = orderVectorElements[j];
296 sm[j + jr*ne] = mphase->
nAtoms(kk,jj);
305 for (j = 0; j < jl; ++j) {
307 for (i = 0; i < ne; ++i) {
308 ss[j] += sm[i + jr*ne] * sm[i + j*ne];
316 for (j = 0; j < jl; ++j) {
317 for (l = 0; l < ne; ++l) {
318 sm[l + jr*ne] -= ss[j] * sm[l + j*ne];
327 for (ml = 0; ml < ne; ++ml) {
328 tmp = sm[ml + jr*ne];
334 if (sa[jr] < 1.0e-6) {
345 if (BasisOptimize_print_lvl >= 1) {
346 kk = orderVectorSpecies[k];
348 writelogf(
" --- %-12.12s", sname.c_str());
349 jj = orderVectorSpecies[jr];
351 writelogf(
"(%9.2g) replaces %-12.12s", molSave, ename.c_str());
352 writelogf(
"(%9.2g) as component %3d\n", molNum[jj], jr);
355 std::swap(orderVectorSpecies[jr], orderVectorSpecies[k]);
365 }
while (jr < (nComponents-1));
406 for (k = 0; k < nComponents; ++k) {
407 kk = orderVectorSpecies[k];
408 for (j = 0; j < nComponents; ++j) {
409 jj = orderVectorElements[j];
410 sm[j + k*ne] = mphase->
nAtoms(kk, jj);
414 for (i = 0; i < nNonComponents; ++i) {
416 kk = orderVectorSpecies[k];
417 for (j = 0; j < nComponents; ++j) {
418 jj = orderVectorElements[j];
419 formRxnMatrix[j + i * ne] = mphase->
nAtoms(kk, jj);
428 writelog(
"ERROR: mlequ returned an error condition\n");
429 throw CanteraError(
"basopt",
"mlequ returned an error condition");
433 if (Cantera::BasisOptimize_print_lvl >= 1) {
435 writelogf(
" --- Number of Components = %d\n", nComponents);
438 for (k = 0; k < nComponents; k++) {
439 kk = orderVectorSpecies[k];
442 writelog(
"\n --- Components Moles: ");
443 for (k = 0; k < nComponents; k++) {
444 kk = orderVectorSpecies[k];
447 writelog(
"\n --- NonComponent | Moles | ");
448 for (i = 0; i < nComponents; i++) {
449 kk = orderVectorSpecies[i];
455 for (i = 0; i < nNonComponents; i++) {
457 kk = orderVectorSpecies[k];
465 for (j = 0; j < nComponents; j++) {
466 writelogf(
" %6.2f", - formRxnMatrix[j + i * ne]);
471 for (i=0; i<77; i++) {
484 static void print_stringTrunc(
const char* str,
int space,
int alignment)
501 int len = strlen(str);
502 if ((len) >= space) {
503 for (i = 0; i < space; i++) {
507 if (alignment == 1) {
509 }
else if (alignment == 2) {
512 ls = (space - len) / 2;
513 rs = space - len - ls;
516 for (i = 0; i < ls; i++) {
522 for (i = 0; i < rs; i++) {
539 static size_t amax(
double* x,
size_t j,
size_t n)
543 for (
size_t i = j + 1; i < n; ++i) {
580 static int mlequ(
double* c,
size_t idem,
size_t n,
double* b,
size_t m)
591 for (i = 0; i < n; ++i) {
592 if (c[i + i * idem] == 0.0) {
596 for (k = i + 1; k < n; ++k) {
597 if (c[k + i * idem] != 0.0) {
602 writelogf(
"vcs_mlequ ERROR: Encountered a zero column: %d\n", i);
607 for (j = 0; j < n; ++j) {
608 c[i + j * idem] += c[k + j * idem];
610 for (j = 0; j < m; ++j) {
611 b[i + j * idem] += b[k + j * idem];
615 for (l = 0; l < n; ++l) {
616 if (l != i && c[l + i * idem] != 0.0) {
617 R = c[l + i * idem] / c[i + i * idem];
618 c[l + i * idem] = 0.0;
619 for (j = i+1; j < n; ++j) {
620 c[l + j * idem] -= c[i + j * idem] * R;
622 for (j = 0; j < m; ++j) {
623 b[l + j * idem] -= b[i + j * idem] * R;
632 for (i = 0; i < n; ++i) {
633 for (j = 0; j < m; ++j) {
634 b[i + j * idem] = -b[i + j * idem] / c[i + i*idem];
678 std::vector<size_t>& orderVectorSpecies,
679 std::vector<size_t>& orderVectorElements)
682 size_t j, k, l, i, jl, ml, jr, ielem, jj, kk=0;
690 size_t nspecies = mphase->
nSpecies();
692 double test = -1.0E10;
694 if (BasisOptimize_print_lvl > 0) {
696 for (i=0; i<77; i++) {
700 writelog(
" --- Subroutine ElemRearrange() called to ");
701 writelog(
"check stoich. coefficient matrix\n");
702 writelog(
" --- and to rearrange the element ordering once\n");
709 if (orderVectorElements.size() < nelements) {
710 orderVectorElements.resize(nelements);
711 for (j = 0; j < nelements; j++) {
712 orderVectorElements[j] = j;
721 if (orderVectorSpecies.size() != nspecies) {
722 orderVectorSpecies.resize(nspecies);
723 for (k = 0; k < nspecies; k++) {
724 orderVectorSpecies[k] = k;
735 if (elementAbundances.size() != nelements) {
736 for (j = 0; j < nelements; j++) {
738 for (k = 0; k < nspecies; k++) {
739 eAbund[j] += fabs(mphase->
nAtoms(k, j));
743 copy(elementAbundances.begin(), elementAbundances.end(),
770 for (ielem = jr; ielem < nelements; ielem++) {
771 kk = orderVectorElements[ielem];
772 if (eAbund[kk] != test && eAbund[kk] > 0.0) {
777 for (ielem = jr; ielem < nelements; ielem++) {
778 kk = orderVectorElements[ielem];
779 if (eAbund[kk] != test) {
785 if (k == nelements) {
790 if (BasisOptimize_print_lvl > 0) {
791 writelogf(
"Error exit: returning with nComponents = %d\n", jr);
818 for (j = 0; j < nComponents; ++j) {
819 jj = orderVectorSpecies[j];
820 kk = orderVectorElements[k];
821 sm[j + jr*nComponents] = mphase->
nAtoms(jj,kk);
830 for (j = 0; j < jl; ++j) {
832 for (i = 0; i < nComponents; ++i) {
833 ss[j] += sm[i + jr*nComponents] * sm[i + j*nComponents];
841 for (j = 0; j < jl; ++j) {
842 for (l = 0; l < nComponents; ++l) {
843 sm[l + jr*nComponents] -= ss[j] * sm[l + j*nComponents];
853 for (ml = 0; ml < nComponents; ++ml) {
854 double tmp = sm[ml + jr*nComponents];
860 if (sa[jr] < 1.0e-6) {
871 if (BasisOptimize_print_lvl > 0) {
872 kk = orderVectorElements[k];
877 kk = orderVectorElements[jr];
883 std::swap(orderVectorElements[jr], orderVectorElements[k]);
891 }
while (jr < (nComponents-1));