16static const double USEDBEFORE = -1;
19 span<size_t> orderVectorSpecies, span<size_t> orderVectorElements,
20 span<double> formRxnMatrix)
26 size_t nspecies = mphase->
nSpecies();
28 checkArraySize(
"BasisOptimize: orderVectorElements", orderVectorElements.size(), ne);
29 checkArraySize(
"BasisOptimize: orderVectorSpecies", orderVectorSpecies.size(), nspecies);
30 checkArraySize(
"BasisOptimize: formRxnMatrix", formRxnMatrix.size(), nspecies * ne);
35 writelog(
" --- Subroutine BASOPT called to ");
36 writelog(
"calculate the number of components and ");
37 writelog(
"evaluate the formation matrix\n");
41 writelog(
" --- Formula Matrix used in BASOPT calculation\n");
43 for (
size_t j = 0; j < ne; j++) {
44 size_t jj = orderVectorElements[j];
48 for (
size_t k = 0; k < nspecies; k++) {
49 size_t kk = orderVectorSpecies[k];
50 writelog(
" --- {:>11.11s} | {:4d} |",
52 for (
size_t j = 0; j < ne; j++) {
53 size_t jj = orderVectorElements[j];
54 double num = mphase->
nAtoms(kk,jj);
66 size_t nComponents = std::min(ne, nspecies);
67 size_t nNonComponents = nspecies - nComponents;
70 usedZeroedSpecies =
false;
73 vector<double> molNum(nspecies,0.0);
78 vector<double> ss(ne, 0.0);
79 vector<double> sa(ne, 0.0);
80 fill(formRxnMatrix.begin(), formRxnMatrix.end(), 0.0);
83 vector<double> molNumBase = molNum;
89 while (jr < nComponents) {
97 size_t kk = max_element(molNum.begin(), molNum.end()) - molNum.begin();
99 for (j = 0; j < nspecies; j++) {
100 if (orderVectorSpecies[j] == kk) {
106 throw CanteraError(
"BasisOptimize",
"orderVectorSpecies contains an error");
109 if (molNum[kk] == 0.0) {
110 usedZeroedSpecies =
true;
113 if (molNum[kk] == USEDBEFORE) {
115 nNonComponents = nspecies - nComponents;
121 molSave = molNum[kk];
122 molNum[kk] = USEDBEFORE;
129 for (j = 0; j < ne; ++j) {
130 size_t jj = orderVectorElements[j];
131 sm(j, jr) = mphase->
nAtoms(kk,jj);
137 for (j = 0; j < jl; ++j) {
139 for (
size_t i = 0; i < ne; ++i) {
140 ss[j] += sm(i, jr) * sm(i, j);
147 for (j = 0; j < jl; ++j) {
148 for (
size_t i = 0; i < ne; ++i) {
149 sm(i, jr) -= ss[j] * sm(i, j);
157 for (
size_t ml = 0; ml < ne; ++ml) {
158 sa[jr] += pow(sm(ml, jr), 2);
162 if (sa[jr] > 1.0e-6) {
170 size_t kk = orderVectorSpecies[k];
172 size_t jj = orderVectorSpecies[jr];
175 writelogf(
"(%9.2g) as component %3d\n", molNum[jj], jr);
177 std::swap(orderVectorSpecies[jr], orderVectorSpecies[k]);
219 sm.
resize(nComponents, nComponents);
220 for (
size_t k = 0; k < nComponents; ++k) {
221 size_t kk = orderVectorSpecies[k];
222 for (
size_t j = 0; j < nComponents; ++j) {
223 size_t jj = orderVectorElements[j];
224 sm(j, k) = mphase->
nAtoms(kk, jj);
228 for (
size_t i = 0; i < nNonComponents; ++i) {
229 size_t k = nComponents + i;
230 size_t kk = orderVectorSpecies[k];
231 for (
size_t j = 0; j < nComponents; ++j) {
232 size_t jj = orderVectorElements[j];
233 formRxnMatrix[j + i * ne] = - mphase->
nAtoms(kk, jj);
238 solve(sm, formRxnMatrix, nNonComponents, ne);
242 writelogf(
" --- Number of Components = %d\n", nComponents);
245 for (
size_t k = 0; k < nComponents; k++) {
246 size_t kk = orderVectorSpecies[k];
249 writelog(
"\n --- Components Moles: ");
250 for (
size_t k = 0; k < nComponents; k++) {
251 size_t kk = orderVectorSpecies[k];
254 writelog(
"\n --- NonComponent | Moles | ");
255 for (
size_t i = 0; i < nComponents; i++) {
256 size_t kk = orderVectorSpecies[i];
261 for (
size_t i = 0; i < nNonComponents; i++) {
262 size_t k = i + nComponents;
263 size_t kk = orderVectorSpecies[k];
268 for (
size_t j = 0; j < nComponents; j++) {
269 writelogf(
" %6.2f", - formRxnMatrix[j + i * ne]);
282 MultiPhase* mphase, span<size_t> orderVectorSpecies,
283 span<size_t> orderVectorElements)
287 size_t nspecies = mphase->
nSpecies();
292 writelog(
" --- Subroutine ElemRearrange() called to ");
293 writelog(
"check stoich. coefficient matrix\n");
294 writelog(
" --- and to rearrange the element ordering once\n");
298 orderVectorElements.size(), nelements);
300 orderVectorSpecies.size(), nspecies);
305 vector<double> eAbund(nelements,0.0);
306 if (elementAbundances.size() != nelements) {
307 for (
size_t j = 0; j < nelements; j++) {
309 for (
size_t k = 0; k < nspecies; k++) {
310 eAbund[j] += fabs(mphase->
nAtoms(k, j));
314 copy(elementAbundances.begin(), elementAbundances.end(),
318 vector<double> sa(nelements,0.0);
319 vector<double> ss(nelements,0.0);
320 vector<double> sm(nelements*nelements,0.0);
325 while (jr < nComponents) {
328 size_t k = nelements;
335 for (
size_t ielem = jr; ielem < nelements; ielem++) {
336 kk = orderVectorElements[ielem];
337 if (eAbund[kk] != USEDBEFORE && eAbund[kk] > 0.0) {
342 for (
size_t ielem = jr; ielem < nelements; ielem++) {
343 kk = orderVectorElements[ielem];
344 if (eAbund[kk] != USEDBEFORE) {
350 if (k == nelements) {
354 writelogf(
"Error exit: returning with nComponents = %d\n", jr);
356 throw CanteraError(
"ElemRearrange",
"Required number of elements not found.");
361 eAbund[kk] = USEDBEFORE;
374 for (
size_t j = 0; j < nComponents; ++j) {
375 size_t jj = orderVectorSpecies[j];
376 kk = orderVectorElements[k];
377 sm[j + jr*nComponents] = mphase->
nAtoms(jj,kk);
383 for (
size_t j = 0; j < jl; ++j) {
385 for (
size_t i = 0; i < nComponents; ++i) {
386 ss[j] += sm[i + jr*nComponents] * sm[i + j*nComponents];
393 for (
size_t j = 0; j < jl; ++j) {
394 for (
size_t i = 0; i < nComponents; ++i) {
395 sm[i + jr*nComponents] -= ss[j] * sm[i + j*nComponents];
403 for (
size_t ml = 0; ml < nComponents; ++ml) {
404 double tmp = sm[ml + jr*nComponents];
408 if (sa[jr] > 1.0e-6) {
415 size_t kk = orderVectorElements[k];
419 kk = orderVectorElements[jr];
423 std::swap(orderVectorElements[jr], orderVectorElements[k]);
Headers for the MultiPhase object that is used to set up multiphase equilibrium problems (see Chemica...
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, double v=0.0) override
Resize the matrix.
A class for multiphase mixtures.
void getMoles(span< double > molNum) const
Get the mole numbers of all species in the multiphase object.
double 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 nSpecies() const
Number of species, summed over all phases.
string speciesName(size_t kGlob) const
Name of species with global index kGlob.
size_t nElements() const
Number of elements.
string elementName(size_t m) const
Returns the name of the global element m.
This file contains definitions for utility functions and text for modules, inputfiles and logging,...
size_t BasisOptimize(bool &usedZeroedSpecies, bool doFormRxn, MultiPhase *mphase, span< size_t > orderVectorSpecies, span< size_t > orderVectorElements, span< double > formRxnMatrix)
Choose the optimum basis of species for the equilibrium calculations.
void ElemRearrange(size_t nComponents, span< const double > elementAbundances, MultiPhase *mphase, span< size_t > orderVectorSpecies, span< size_t > orderVectorElements)
Handles the potential rearrangement of the constraint equations represented by the Formula Matrix.
void writelogf(const char *fmt, const Args &... args)
Write a formatted message to the screen.
void writelog(const string &fmt, const Args &... args)
Write a formatted message to the screen.
Namespace for the Cantera kernel.
const size_t npos
index returned by functions to indicate "no position"
void solve(DenseMatrix &A, span< double > b, size_t nrhs, size_t ldb)
Solve Ax = b. Array b is overwritten on exit with x.
int BasisOptimize_print_lvl
External int that is used to turn on debug printing for the BasisOptimize program.
void checkArraySize(const char *procedure, size_t available, size_t required)
Wrapper for throwing ArraySizeError.
Various templated functions that carry out common vector and polynomial operations (see Templated Arr...