Cantera  2.5.1
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 https://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_SOLVE::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 }
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:61
size_t m_numPhases
Number of Phases in the problem.
Definition: vcs_solve.h:1068
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_int m_elType
Type of the element constraint.
Definition: vcs_solve.h:1385
size_t m_nelem
Number of element constraints in the problem.
Definition: vcs_solve.h:1047
vector_fp m_elemAbundances
Element abundances vector.
Definition: vcs_solve.h:1222
int m_debug_print_lvl
Debug printing lvl.
Definition: vcs_solve.h:1498
vector_fp m_elemAbundancesGoal
Element abundances vector Goals.
Definition: vcs_solve.h:1231
Array2D m_formulaMatrix
Formula matrix for the problem.
Definition: vcs_solve.h:1076
size_t m_numComponents
Number of components calculated for the problem.
Definition: vcs_solve.h:1050
vector_int m_elementActive
Specifies whether an element constraint is active.
Definition: vcs_solve.h:1391
size_t m_nsp
Total number of species in the problems.
Definition: vcs_solve.h:1044
std::vector< std::unique_ptr< vcs_VolPhase > > m_VolPhaseList
Array of Phase Structures. Length = number of phases.
Definition: vcs_solve.h:1394
std::vector< size_t > m_elementMapIndex
Index vector that keeps track of the rearrangement of the elements.
Definition: vcs_solve.h:1333
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.
std::vector< std::string > m_elementName
Vector of strings containing the element names.
Definition: vcs_solve.h:1370
Phase information and Phase calculations for vcs.
Definition: vcs_VolPhase.h:82
size_t elemGlobalIndex(const size_t e) const
Returns the global index of the local element index for the phase.
void setElemGlobalIndex(const size_t eLocal, const size_t eGlobal)
sets a local phase element to a global index value
size_t nElemConstraints() const
Returns the number of element constraints.
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
#define AssertThrowMsg(expr, procedure,...)
Assertion must be true or an error is thrown.
Definition: ctexceptions.h:265
Namespace for the Cantera kernel.
Definition: AnyMap.cpp:264
Contains declarations for string manipulation functions within Cantera.
Header for the object representing each phase within vcs.
#define VCS_SUCCESS
Definition: vcs_defs.h:18
#define plogf
define this Cantera function to replace printf
Definition: vcs_internal.h:18
Header file for the internal object that holds the vcs equilibrium problem (see Class VCS_SOLVE and E...