18static const double USEDBEFORE = -1;
21 std::vector<size_t>& orderVectorSpecies,
22 std::vector<size_t>& orderVectorElements,
29 size_t nspecies = mphase->
nSpecies();
32 if (orderVectorElements.size() < ne) {
33 orderVectorElements.resize(ne);
34 iota(orderVectorElements.begin(), orderVectorElements.end(), 0);
38 if (orderVectorSpecies.size() != nspecies) {
39 orderVectorSpecies.resize(nspecies);
40 iota(orderVectorSpecies.begin(), orderVectorSpecies.end(), 0);
46 writelog(
" --- Subroutine BASOPT called to ");
47 writelog(
"calculate the number of components and ");
48 writelog(
"evaluate the formation matrix\n");
52 writelog(
" --- Formula Matrix used in BASOPT calculation\n");
54 for (
size_t j = 0; j < ne; j++) {
55 size_t jj = orderVectorElements[j];
59 for (
size_t k = 0; k < nspecies; k++) {
60 size_t kk = orderVectorSpecies[k];
61 writelog(
" --- {:>11.11s} | {:4d} |",
63 for (
size_t j = 0; j < ne; j++) {
64 size_t jj = orderVectorElements[j];
65 double num = mphase->
nAtoms(kk,jj);
77 size_t nComponents = std::min(ne, nspecies);
78 size_t nNonComponents = nspecies - nComponents;
81 *usedZeroedSpecies =
false;
91 if (formRxnMatrix.size() < nspecies*ne) {
92 formRxnMatrix.resize(nspecies*ne, 0.0);
102 while (jr < nComponents) {
110 size_t kk = max_element(molNum.begin(), molNum.end()) - molNum.begin();
112 for (j = 0; j < nspecies; j++) {
113 if (orderVectorSpecies[j] == kk) {
119 throw CanteraError(
"BasisOptimize",
"orderVectorSpecies contains an error");
122 if (molNum[kk] == 0.0) {
123 *usedZeroedSpecies =
true;
126 if (molNum[kk] == USEDBEFORE) {
128 nNonComponents = nspecies - nComponents;
134 molSave = molNum[kk];
135 molNum[kk] = USEDBEFORE;
142 for (j = 0; j < ne; ++j) {
143 size_t jj = orderVectorElements[j];
144 sm(j, jr) = mphase->
nAtoms(kk,jj);
150 for (j = 0; j < jl; ++j) {
152 for (
size_t i = 0; i < ne; ++i) {
153 ss[j] += sm(i, jr) * sm(i, j);
160 for (j = 0; j < jl; ++j) {
161 for (
size_t i = 0; i < ne; ++i) {
162 sm(i, jr) -= ss[j] * sm(i, j);
170 for (
size_t ml = 0; ml < ne; ++ml) {
171 sa[jr] += pow(sm(ml, jr), 2);
175 if (sa[jr] > 1.0e-6) {
183 size_t kk = orderVectorSpecies[k];
185 size_t jj = orderVectorSpecies[jr];
188 writelogf(
"(%9.2g) as component %3d\n", molNum[jj], jr);
190 std::swap(orderVectorSpecies[jr], orderVectorSpecies[k]);
232 sm.
resize(nComponents, nComponents);
233 for (
size_t k = 0; k < nComponents; ++k) {
234 size_t kk = orderVectorSpecies[k];
235 for (
size_t j = 0; j < nComponents; ++j) {
236 size_t jj = orderVectorElements[j];
237 sm(j, k) = mphase->
nAtoms(kk, jj);
241 for (
size_t i = 0; i < nNonComponents; ++i) {
242 size_t k = nComponents + i;
243 size_t kk = orderVectorSpecies[k];
244 for (
size_t j = 0; j < nComponents; ++j) {
245 size_t jj = orderVectorElements[j];
246 formRxnMatrix[j + i * ne] = - mphase->
nAtoms(kk, jj);
251 solve(sm, formRxnMatrix.
data(), nNonComponents, ne);
255 writelogf(
" --- Number of Components = %d\n", nComponents);
258 for (
size_t k = 0; k < nComponents; k++) {
259 size_t kk = orderVectorSpecies[k];
262 writelog(
"\n --- Components Moles: ");
263 for (
size_t k = 0; k < nComponents; k++) {
264 size_t kk = orderVectorSpecies[k];
267 writelog(
"\n --- NonComponent | Moles | ");
268 for (
size_t i = 0; i < nComponents; i++) {
269 size_t kk = orderVectorSpecies[i];
274 for (
size_t i = 0; i < nNonComponents; i++) {
275 size_t k = i + nComponents;
276 size_t kk = orderVectorSpecies[k];
281 for (
size_t j = 0; j < nComponents; j++) {
282 writelogf(
" %6.2f", - formRxnMatrix[j + i * ne]);
296 std::vector<size_t>& orderVectorSpecies,
297 std::vector<size_t>& orderVectorElements)
301 size_t nspecies = mphase->
nSpecies();
306 writelog(
" --- Subroutine ElemRearrange() called to ");
307 writelog(
"check stoich. coefficient matrix\n");
308 writelog(
" --- and to rearrange the element ordering once\n");
312 if (orderVectorElements.size() < nelements) {
313 orderVectorElements.resize(nelements);
314 for (
size_t j = 0; j < nelements; j++) {
315 orderVectorElements[j] = j;
321 if (orderVectorSpecies.size() != nspecies) {
322 orderVectorSpecies.resize(nspecies);
323 for (
size_t k = 0; k < nspecies; k++) {
324 orderVectorSpecies[k] = k;
332 if (elementAbundances.size() != nelements) {
333 for (
size_t j = 0; j < nelements; j++) {
335 for (
size_t k = 0; k < nspecies; k++) {
336 eAbund[j] += fabs(mphase->
nAtoms(k, j));
340 copy(elementAbundances.begin(), elementAbundances.end(),
351 while (jr < nComponents) {
354 size_t k = nelements;
361 for (
size_t ielem = jr; ielem < nelements; ielem++) {
362 kk = orderVectorElements[ielem];
363 if (eAbund[kk] != USEDBEFORE && eAbund[kk] > 0.0) {
368 for (
size_t ielem = jr; ielem < nelements; ielem++) {
369 kk = orderVectorElements[ielem];
370 if (eAbund[kk] != USEDBEFORE) {
376 if (k == nelements) {
380 writelogf(
"Error exit: returning with nComponents = %d\n", jr);
382 throw CanteraError(
"ElemRearrange",
"Required number of elements not found.");
387 eAbund[kk] = USEDBEFORE;
400 for (
size_t j = 0; j < nComponents; ++j) {
401 size_t jj = orderVectorSpecies[j];
402 kk = orderVectorElements[k];
403 sm[j + jr*nComponents] = mphase->
nAtoms(jj,kk);
409 for (
size_t j = 0; j < jl; ++j) {
411 for (
size_t i = 0; i < nComponents; ++i) {
412 ss[j] += sm[i + jr*nComponents] * sm[i + j*nComponents];
419 for (
size_t j = 0; j < jl; ++j) {
420 for (
size_t i = 0; i < nComponents; ++i) {
421 sm[i + jr*nComponents] -= ss[j] * sm[i + j*nComponents];
429 for (
size_t ml = 0; ml < nComponents; ++ml) {
430 double tmp = sm[ml + jr*nComponents];
434 if (sa[jr] > 1.0e-6) {
441 size_t kk = orderVectorElements[k];
445 kk = orderVectorElements[jr];
449 std::swap(orderVectorElements[jr], orderVectorElements[k]);
Headers for the MultiPhase object that is used to set up multiphase equilibrium problems (see Classes...
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.
This file contains definitions for utility functions and text for modules, inputfiles,...
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.
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.
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.
int BasisOptimize_print_lvl
External int that is used to turn on debug printing for the BasisOptimize program.
int solve(DenseMatrix &A, double *b, size_t nrhs=1, size_t ldb=0)
Solve Ax = b. Array b is overwritten on exit with x.
Various templated functions that carry out common vector operations (see Templated Utility Functions)...