Cantera  2.4.0
vcs_elem_rearrange.cpp
Go to the documentation of this file.
1 /**
2  * @file vcs_elem_rearrange.cpp
3  * Contains implementations for rearranging the element columns, and
4  * it contains the algorithm for choosing the rearrangement.
5  */
6 
7 // This file is part of Cantera. See License.txt in the top-level directory or
8 // at http://www.cantera.org/license.txt for license and copyright information.
9 
14 
15 namespace Cantera
16 {
17 
18 int VCS_SOLVE::vcs_elem_rearrange(double* const aw, double* const sa,
19  double* const sm, double* const ss)
20 {
21  size_t ncomponents = m_numComponents;
22  if (m_debug_print_lvl >= 2) {
23  plogf(" ");
24  writeline('-', 77);
25  plogf(" --- Subroutine elem_rearrange() called to ");
26  plogf("check stoich. coefficient matrix\n");
27  plogf(" --- and to rearrange the element ordering once\n");
28  }
29 
30  // Use a temporary work array for the element numbers
31  // Also make sure the value of test is unique.
32  bool lindep = true;
33  double test = -1.0E10;
34  while (lindep) {
35  lindep = false;
36  for (size_t i = 0; i < m_nelem; ++i) {
37  test -= 1.0;
38  aw[i] = m_elemAbundancesGoal[i];
39  if (test == aw[i]) {
40  lindep = true;
41  }
42  }
43  }
44 
45  // Top of a loop of some sort based on the index JR. JR is the current
46  // number independent elements found.
47  size_t jr = 0;
48  while (jr < ncomponents) {
49  size_t k;
50 
51  // Top of another loop point based on finding a linearly independent
52  // species
53  while (true) {
54  // Search the remaining part of the mole fraction vector, AW, for
55  // the largest remaining species. Return its identity in K.
56  k = m_nelem;
57  for (size_t ielem = jr; ielem < m_nelem; ielem++) {
58  if (m_elementActive[ielem] && aw[ielem] != test) {
59  k = ielem;
60  break;
61  }
62  }
63  if (k == m_nelem) {
64  throw CanteraError("vcs_elem_rearrange",
65  "Shouldn't be here. Algorithm misfired.");
66  }
67 
68  // Assign a large negative number to the element that we have just
69  // found, in order to take it out of further consideration.
70  aw[k] = test;
71 
72  // CHECK LINEAR INDEPENDENCE OF CURRENT FORMULA MATRIX LINE WITH
73  // PREVIOUS LINES OF THE FORMULA MATRIX
74  //
75  // Modified Gram-Schmidt Method, p. 202 Dalquist QR factorization of
76  // a matrix without row pivoting.
77  size_t jl = jr;
78 
79  // Fill in the row for the current element, k, under consideration
80  // The row will contain the Formula matrix value for that element
81  // from the current component.
82  for (size_t j = 0; j < ncomponents; ++j) {
83  sm[j + jr*ncomponents] = m_formulaMatrix(j,k);
84  }
85  if (jl > 0) {
86  // Compute the coefficients of JA column of the the upper
87  // triangular R matrix, SS(J) = R_J_JR (this is slightly
88  // different than Dalquist) R_JA_JA = 1
89  for (size_t j = 0; j < jl; ++j) {
90  ss[j] = 0.0;
91  for (size_t i = 0; i < ncomponents; ++i) {
92  ss[j] += sm[i + jr*ncomponents] * sm[i + j*ncomponents];
93  }
94  ss[j] /= sa[j];
95  }
96 
97  // Now make the new column, (*,JR), orthogonal to the previous
98  // columns
99  for (size_t j = 0; j < jl; ++j) {
100  for (size_t i = 0; i < ncomponents; ++i) {
101  sm[i + jr*ncomponents] -= ss[j] * sm[i + j*ncomponents];
102  }
103  }
104  }
105 
106  // Find the new length of the new column in Q. It will be used in
107  // the denominator in future row calcs.
108  sa[jr] = 0.0;
109  for (size_t ml = 0; ml < ncomponents; ++ml) {
110  sa[jr] += pow(sm[ml + jr*ncomponents], 2);
111  }
112  // IF NORM OF NEW ROW .LT. 1E-6 REJECT
113  if (sa[jr] > 1.0e-6) {
114  break;
115  }
116  }
117  // REARRANGE THE DATA
118  if (jr != k) {
119  if (m_debug_print_lvl >= 2) {
120  plogf(" --- %-2.2s(%9.2g) replaces %-2.2s(%9.2g) as element %3d\n",
122  m_elementName[jr], m_elemAbundancesGoal[jr], jr);
123  }
124  vcs_switch_elem_pos(jr, k);
125  std::swap(aw[jr], aw[k]);
126  }
127 
128  // If we haven't found enough components, go back and find some more.
129  jr++;
130  }
131  return VCS_SUCCESS;
132 }
133 
134 void VCS_SOLVE::vcs_switch_elem_pos(size_t ipos, size_t jpos)
135 {
136  if (ipos == jpos) {
137  return;
138  }
139  AssertThrowMsg(ipos < m_nelem && jpos < m_nelem,
140  "vcs_switch_elem_pos",
141  "inappropriate args: {} {}", ipos, jpos);
142 
143  // Change the element Global Index list in each vcs_VolPhase object
144  // to reflect the switch in the element positions.
145  for (size_t iph = 0; iph < m_numPhases; iph++) {
146  vcs_VolPhase* volPhase = m_VolPhaseList[iph].get();
147  for (size_t e = 0; e < volPhase->nElemConstraints(); e++) {
148  if (volPhase->elemGlobalIndex(e) == ipos) {
149  volPhase->setElemGlobalIndex(e, jpos);
150  }
151  if (volPhase->elemGlobalIndex(e) == jpos) {
152  volPhase->setElemGlobalIndex(e, ipos);
153  }
154  }
155  }
156  std::swap(m_elemAbundancesGoal[ipos], m_elemAbundancesGoal[jpos]);
157  std::swap(m_elemAbundances[ipos], m_elemAbundances[jpos]);
158  std::swap(m_elementMapIndex[ipos], m_elementMapIndex[jpos]);
159  std::swap(m_elType[ipos], m_elType[jpos]);
160  std::swap(m_elementActive[ipos], m_elementActive[jpos]);
161  for (size_t j = 0; j < m_nsp; ++j) {
162  std::swap(m_formulaMatrix(j,ipos), m_formulaMatrix(j,jpos));
163  }
164  std::swap(m_elementName[ipos], m_elementName[jpos]);
165 }
166 }
int vcs_elem_rearrange(double *const aw, double *const sa, double *const sm, double *const ss)
Rearrange the constraint equations represented by the Formula Matrix so that the operational ones are...
vector_fp m_elemAbundances
Element abundances vector.
Definition: vcs_solve.h:1222
size_t nElemConstraints() const
Returns the number of element constraints.
std::vector< size_t > m_elementMapIndex
Index vector that keeps track of the rearrangement of the elements.
Definition: vcs_solve.h:1333
std::vector< std::unique_ptr< vcs_VolPhase > > m_VolPhaseList
Array of Phase Structures. Length = number of phases.
Definition: vcs_solve.h:1394
size_t elemGlobalIndex(const size_t e) const
Returns the global index of the local element index for the phase.
vector_int m_elementActive
Specifies whether an element constraint is active.
Definition: vcs_solve.h:1391
std::vector< std::string > m_elementName
Vector of strings containing the element names.
Definition: vcs_solve.h:1370
Header file for the internal object that holds the vcs equilibrium problem (see Class VCS_SOLVE and E...
Header for the object representing each phase within vcs.
#define VCS_SUCCESS
Definition: vcs_defs.h:18
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:65
int m_debug_print_lvl
Debug printing lvl.
Definition: vcs_solve.h:1498
size_t m_numComponents
Number of components calculated for the problem.
Definition: vcs_solve.h:1050
vector_fp m_elemAbundancesGoal
Element abundances vector Goals.
Definition: vcs_solve.h:1231
Phase information and Phase calculations for vcs.
Definition: vcs_VolPhase.h:81
#define AssertThrowMsg(expr, procedure,...)
Assertion must be true or an error is thrown.
Definition: ctexceptions.h:264
Array2D m_formulaMatrix
Formula matrix for the problem.
Definition: vcs_solve.h:1076
size_t m_nsp
Total number of species in the problems.
Definition: vcs_solve.h:1044
Contains declarations for string manipulation functions within Cantera.
#define plogf
define this Cantera function to replace printf
Definition: vcs_internal.h:18
vector_int m_elType
Type of the element constraint.
Definition: vcs_solve.h:1385
Namespace for the Cantera kernel.
Definition: AnyMap.cpp:8
size_t m_nelem
Number of element constraints in the problem.
Definition: vcs_solve.h:1047
size_t m_numPhases
Number of Phases in the problem.
Definition: vcs_solve.h:1068
void vcs_switch_elem_pos(size_t ipos, size_t jpos)
Swaps the indices for all of the global data for two elements, ipos and jpos.
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
void setElemGlobalIndex(const size_t eLocal, const size_t eGlobal)
sets a local phase element to a global index value