Cantera  2.0
MultiPhase.h
Go to the documentation of this file.
1 /**
2  * @file MultiPhase.h
3  * Headers for the \link Cantera::MultiPhase MultiPhase\endlink
4  * object that is used to set up multiphase equilibrium problems (see \ref equilfunctions).
5  */
6 // Copyright 2004 California Institute of Technology
7 
8 
9 #ifndef CT_MULTIPHASE_H
10 #define CT_MULTIPHASE_H
11 
12 #include "cantera/base/ct_defs.h"
15 
16 namespace Cantera
17 {
18 
19 //! A class for multiphase mixtures. The mixture can contain any
20 //! number of phases of any type.
21 /*!
22  * This object is the basic tool used by Cantera for use in
23  * Multiphase equilibrium calculations.
24  *
25  * It is a container for a set of phases. Each phase has a
26  * given number of kmoles. Therefore, MultiPhase may be considered
27  * an "extrinsic" thermodynamic object, in contrast to the ThermoPhase
28  * object, which is an "intrinsic" thermodynamic object.
29  *
30  * MultiPhase may be considered to be "upstream" of the ThermoPhase
31  * objects in the sense that setting a property within MultiPhase,
32  * such as temperature, pressure, or species mole number,
33  * affects the underlying ThermoPhase object, but not the
34  * other way around.
35  *
36  * All phases have the same
37  * temperature and pressure, and a specified number of moles for
38  * each phase.
39  * The phases do not need to have the same elements. For example,
40  * a mixture might consist of a gaseous phase with elements (H,
41  * C, O, N), a solid carbon phase containing only element C,
42  * etc. A master element set will be constructed for the mixture
43  * that is the intersection of the elements of each phase.
44  *
45  * Below, reference is made to global species and global elements.
46  * These refer to the collective species and elements encompassing
47  * all of the phases tracked by the object.
48  *
49  * The global element list kept by this object is an
50  * intersection of the element lists of all the phases that
51  * comprise the MultiPhase.
52  *
53  * The global species list kept by this object is a
54  * concatenated list of all of the species in all the phases that
55  * comprise the MultiPhase. The ordering of species is contiguous
56  * with respect to the phase id.
57  *
58  * @ingroup equilfunctions
59  */
61 {
62 
63 public:
64  //! Shorthand for an index variable that can't be negative
65  typedef size_t index_t;
66 
67  //! Constructor.
68  /*!
69  * The constructor takes no arguments, since
70  * phases are added using method addPhase().
71  */
72  MultiPhase();
73 
74  //! Copy Constructor
75  /*!
76  * @param right Object to be copied
77  */
78  MultiPhase(const MultiPhase& right);
79 
80  //! Destructor.
81  /*!
82  * Does nothing. Class MultiPhase does not take
83  * "ownership" (i.e. responsibility for destroying) the
84  * phase objects.
85  */
86  virtual ~MultiPhase();
87 
88  //! Assignment operator
89  /*!
90  * @param right Object to be copied
91  */
92  MultiPhase& operator=(const MultiPhase& right);
93 
94  //! Add a vector of phases to the mixture
95  /*!
96  * See the single addPhases command. This just does a bunch of phases
97  * at one time
98  * @param phases Vector of pointers to phases
99  * @param phaseMoles Vector of mole numbers in each phase (kmol)
100  */
101  void addPhases(std::vector<ThermoPhase*>& phases, const vector_fp& phaseMoles);
102 
103  //! Add all phases present in 'mix' to this mixture.
104  /*!
105  * @param mix Add all of the phases in another MultiPhase
106  * object to the current object.
107  */
108  void addPhases(MultiPhase& mix);
109 
110  //! Add a phase to the mixture.
111  /*!
112  * This function must be called before the init() function is called,
113  * which serves to freeze the MultiPhase.
114  *
115  * @param p pointer to the phase object
116  * @param moles total number of moles of all species in this phase
117  */
118  void addPhase(ThermoPhase* p, doublereal moles);
119 
120  /// Number of elements.
121  size_t nElements() const {
122  return m_nel;
123  }
124 
125  //! Check that the specified element index is in range
126  //! Throws an exception if m is greater than nElements()-1
127  void checkElementIndex(size_t m) const;
128 
129  //! Check that an array size is at least nElements()
130  //! Throws an exception if mm is less than nElements(). Used before calls
131  //! which take an array pointer.
132  void checkElementArraySize(size_t mm) const;
133 
134  //! Returns the string name of the global element \a m.
135  /*!
136  * @param m index of the global element
137  */
138  std::string elementName(size_t m) const;
139 
140  //! Returns the index of the element with name \a name.
141  /*!
142  * @param name String name of the global element
143  */
144  size_t elementIndex(std::string name) const;
145 
146  //! Number of species, summed over all phases.
147  size_t nSpecies() const {
148  return m_nsp;
149  }
150 
151  //! Check that the specified species index is in range
152  //! Throws an exception if k is greater than nSpecies()-1
153  void checkSpeciesIndex(size_t k) const;
154 
155  //! Check that an array size is at least nSpecies()
156  //! Throws an exception if kk is less than nSpecies(). Used before calls
157  //! which take an array pointer.
158  void checkSpeciesArraySize(size_t kk) const;
159 
160  //! Name of species with global index \a kGlob
161  /*!
162  * @param kGlob global species index
163  */
164  std::string speciesName(const size_t kGlob) const;
165 
166  //! Returns the Number of atoms of global element \a mGlob in
167  //! global species \a kGlob.
168  /*!
169  * @param kGlob global species index
170  * @param mGlob global element index
171  * @return returns the number of atoms.
172  */
173  doublereal nAtoms(const size_t kGlob, const size_t mGlob) const;
174 
175  /// Returns the global Species mole fractions.
176  /*!
177  * Write the array of species mole
178  * fractions into array \c x. The mole fractions are
179  * normalized to sum to one in each phase.
180  *
181  * @param x vector of mole fractions.
182  * Length = number of global species.
183  */
184  void getMoleFractions(doublereal* const x) const;
185 
186  //! Process phases and build atomic composition array.
187  /*!This method
188  * must be called after all phases are added, before doing
189  * anything else with the mixture. After init() has been called,
190  * no more phases may be added.
191  */
192  void init();
193 
194  //! Returns the name of the n'th phase
195  /*!
196  * @param iph phase Index
197  */
198  std::string phaseName(const index_t iph) const;
199 
200  //! Returns the index, given the phase name
201  /*!
202  * @param pName Name of the phase
203  *
204  * @return returns the index. A value of -1 means
205  * the phase isn't in the object.
206  */
207  int phaseIndex(const std::string& pName) const;
208 
209  //! Return the number of moles in phase n.
210  /*!
211  * @param n Index of the phase.
212  */
213  doublereal phaseMoles(const index_t n) const;
214 
215  //! Set the number of moles of phase with index n.
216  /*!
217  * @param n Index of the phase
218  * @param moles Number of moles in the phase (kmol)
219  */
220  void setPhaseMoles(const index_t n, const doublereal moles);
221 
222  /// Return a %ThermoPhase reference to phase n.
223  /*! The state of phase n is
224  * also updated to match the state stored locally in the
225  * mixture object.
226  *
227  * @param n Phase Index
228  *
229  * @return Reference to the %ThermoPhase object for the phase
230  */
232 
233  //! Check that the specified phase index is in range
234  //! Throws an exception if m is greater than nPhases()
235  void checkPhaseIndex(size_t m) const;
236 
237  //! Check that an array size is at least nPhases()
238  //! Throws an exception if mm is less than nPhases(). Used before calls
239  //! which take an array pointer.
240  void checkPhaseArraySize(size_t mm) const;
241 
242  //! Returns the moles of global species \c k.
243  /*!
244  * Returns the moles of global species k.
245  * units = kmol
246  *
247  * @param kGlob Global species index k
248  */
249  doublereal speciesMoles(index_t kGlob) const;
250 
251  //! Return the global index of the species belonging to phase number \c p
252  //! with local index \c k within the phase.
253  /*!
254  * Returns the index of the global species
255  *
256  * @param k local index of the species within the phase
257  * @param p index of the phase
258  */
259  size_t speciesIndex(index_t k, index_t p) const {
260  return m_spstart[p] + k;
261  }
262 
263  //! Return the global index of the species belonging to phase name \c phaseName
264  //! with species name \c speciesName
265  /*!
266  * Returns the index of the global species
267  *
268  * @param speciesName Species Name
269  * @param phaseName Phase Name
270  *
271  * @return returns the global index
272  *
273  * If the species or phase name is not recognized, this routine throws
274  * a CanteraError.
275  */
276  size_t speciesIndex(std::string speciesName, std::string phaseName);
277 
278  /// Minimum temperature for which all solution phases have
279  /// valid thermo data. Stoichiometric phases are not
280  /// considered, since they may have thermo data only valid for
281  /// conditions for which they are stable.
282  doublereal minTemp() const {
283  return m_Tmin;
284  }
285 
286  /// Maximum temperature for which all solution phases have
287  /// valid thermo data. Stoichiometric phases are not
288  /// considered, since they may have thermo data only valid for
289  /// conditions for which they are stable.
290  doublereal maxTemp() const {
291  return m_Tmax;
292  }
293 
294  //! Total charge summed over all phases (Coulombs).
295  doublereal charge() const;
296 
297  /// Charge (Coulombs) of phase with index \a p.
298  /*!
299  * @param p Phase Index
300  */
301  doublereal phaseCharge(index_t p) const;
302 
303  //! Total moles of global element \a m, summed over all phases.
304  /*!
305  * @param m Index of the global element
306  */
307  doublereal elementMoles(index_t m) const;
308 
309  //! Returns a vector of Chemical potentials.
310  /*!
311  * Write into array \a mu the chemical
312  * potentials of all species [J/kmol]. The chemical
313  * potentials are related to the activities by
314  *
315  * \f$
316  * \mu_k = \mu_k^0(T, P) + RT \ln a_k.
317  * \f$.
318  *
319  * @param mu Chemical potential vector.
320  * Length = num global species.
321  * Units = J/kmol.
322  */
323  void getChemPotentials(doublereal* mu) const;
324 
325  /// Returns a vector of Valid chemical potentials.
326  /*!
327  * Write into array \a mu the
328  * chemical potentials of all species with thermo data valid
329  * for the current temperature [J/kmol]. For other species,
330  * set the chemical potential to the value \a not_mu. If \a
331  * standard is set to true, then the values returned are
332  * standard chemical potentials.
333  *
334  * This method is designed for use in computing chemical
335  * equilibrium by Gibbs minimization. For solution phases (more
336  * than one species), this does the same thing as
337  * getChemPotentials. But for stoichiometric phases, this writes
338  * into array \a mu the user-specified value \a not_mu instead of
339  * the chemical potential if the temperature is outside the range
340  * for which the thermo data for the one species in the phase are
341  * valid. The need for this arises since many condensed phases
342  * have thermo data fit only for the temperature range for which
343  * they are stable. For example, in the NASA database, the fits
344  * for H2O(s) are only done up to 0 C, the fits for H2O(L) are
345  * only done from 0 C to 100 C, etc. Using the polynomial fits outside
346  * the range for which the fits were done can result in spurious
347  * chemical potentials, and can lead to condensed phases
348  * appearing when in fact they should be absent.
349  *
350  * By setting \a not_mu to a large positive value, it is possible
351  * to force routines which seek to minimize the Gibbs free energy
352  * of the mixture to zero out any phases outside the temperature
353  * range for which their thermo data are valid.
354  *
355  * @param not_mu Value of the chemical potential to set
356  * species in phases, for which the thermo data
357  * is not valid
358  *
359  * @param mu Vector of chemical potentials
360  * length = Global species, units = J kmol-1
361  *
362  * @param standard If this method is called with \a standard set to true, then
363  * the composition-independent standard chemical potentials are
364  * returned instead of the composition-dependent chemical
365  * potentials.
366  */
367  void getValidChemPotentials(doublereal not_mu, doublereal* mu,
368  bool standard = false) const;
369 
370  //! Temperature [K].
371  doublereal temperature() const {
372  return m_temp;
373  }
374 
375  //! Set the mixture to a state of chemical equilibrium.
376  /*!
377  * @param XY Integer flag specifying properties to hold fixed.
378  * @param err Error tolerance for \f$\Delta \mu/RT \f$ for
379  * all reactions. Also used as the relative error tolerance
380  * for the outer loop.
381  * @param maxsteps Maximum number of steps to take in solving
382  * the fixed TP problem.
383  * @param maxiter Maximum number of "outer" iterations for
384  * problems holding fixed something other than (T,P).
385  * @param loglevel Level of diagnostic output, written to a
386  * file in HTML format.
387  */
388  doublereal equilibrate(int XY, doublereal err = 1.0e-9,
389  int maxsteps = 1000, int maxiter = 200, int loglevel = -99);
390 
391 
392  /// Set the temperature [K].
393  /*!
394  * @param T value of the temperature (Kelvin)
395  */
396  void setTemperature(const doublereal T);
397 
398  //! Set the state of the underlying ThermoPhase objects in one call
399  /*!
400  * @param T Temperature of the system (kelvin)
401  * @param Pres pressure of the system (pascal)
402  * (kmol)
403  */
404  void setState_TP(const doublereal T, const doublereal Pres);
405 
406  //! Set the state of the underlying ThermoPhase objects in one call
407  /*!
408  * @param T Temperature of the system (kelvin)
409  * @param Pres pressure of the system (pascal)
410  * @param Moles Vector of mole numbers of all the species in all the phases
411  * (kmol)
412  */
413  void setState_TPMoles(const doublereal T, const doublereal Pres, const doublereal* Moles);
414 
415  /// Pressure [Pa].
416  doublereal pressure() const {
417  return m_press;
418  }
419 
420  /// Volume [m^3].
421  /*!
422  * Returns the cummulative sum of the volumes of all the
423  * phases in the %MultiPhase.
424  */
425  doublereal volume() const;
426 
427  //! Set the pressure [Pa].
428  /*!
429  * @param P Set the pressure in the %MultiPhase object (Pa)
430  */
431  void setPressure(doublereal P) {
432  m_press = P;
433  updatePhases();
434  }
435 
436  /// Enthalpy [J].
437  doublereal enthalpy() const;
438 
439  /// Enthalpy [J].
440  doublereal IntEnergy() const;
441 
442  /// Entropy [J/K].
443  doublereal entropy() const;
444 
445  /// Gibbs function [J].
446  doublereal gibbs() const;
447 
448  /// Heat capacity at constant pressure [J/K].
449  doublereal cp() const;
450 
451  /// Number of phases.
452  index_t nPhases() const {
453  return m_np;
454  }
455 
456  //! Return true is species \a kGlob is a species in a
457  //! multicomponent solution phase.
458  /*!
459  * @param kGlob index of the global species
460  */
461  bool solutionSpecies(index_t kGlob) const;
462 
463  //! Returns the phase index of the Kth "global" species
464  /*!
465  * @param kGlob Global species index.
466  *
467  * @return
468  * Returns the index of the owning phase.
469  */
470  size_t speciesPhaseIndex(const index_t kGlob) const;
471 
472  //! Returns the mole fraction of global species k
473  /*!
474  * @param kGlob Index of the global species.
475  */
476  doublereal moleFraction(const index_t kGlob) const;
477 
478  //! Set the Mole fractions of the nth phase
479  /*!
480  * This function sets the mole fractions of the
481  * nth phase. Note, the mole number of the phase
482  * stays constant
483  *
484  * @param n ID of the phase
485  * @param x Vector of input mole fractions.
486  */
487  void setPhaseMoleFractions(const index_t n, const doublereal* const x);
488 
489  //! Set the number numbers of species in the MultiPhase
490  /*!
491  * @param xMap CompositionMap of the species with
492  * nonzero mole numbers
493  * units = kmol.
494  */
495  void setMolesByName(compositionMap& xMap);
496 
497  //! Set the Moles via a string containing their names.
498  /*!
499  * The string x is in the form of a composition map
500  * Species which are not listed by name in the composition
501  * map are set to zero.
502  *
503  * @param x string x in the form of a composition map
504  * where values are the moles of the species.
505  */
506  void setMolesByName(const std::string& x);
507 
508 
509  //! Return a vector of global species mole numbers
510  /*!
511  * Returns a vector of the number of moles of each species
512  * in the multiphase object.
513  *
514  * @param molNum Vector of doubles of length nSpecies
515  * containing the global mole numbers
516  * (kmol).
517  */
518  void getMoles(doublereal* molNum) const;
519 
520  //! Sets all of the global species mole numbers
521  /*!
522  * Sets the number of moles of each species
523  * in the multiphase object.
524  *
525  * @param n Vector of doubles of length nSpecies
526  * containing the global mole numbers
527  * (kmol).
528  */
529  void setMoles(const doublereal* n);
530 
531 
532  //! Adds moles of a certain species to the mixture
533  /*!
534  * @param indexS Index of the species in the MultiPhase object
535  * @param addedMoles Value of the moles that are added to the species.
536  */
537  void addSpeciesMoles(const int indexS, const doublereal addedMoles);
538 
539  //! Retrieves a vector of element abundances
540  /*!
541  * @param elemAbundances Vector of element abundances
542  * Length = number of elements in the MultiPhase object.
543  * Index is the global element index
544  * units is in kmol.
545  */
546  void getElemAbundances(doublereal* elemAbundances) const;
547 
548  //! Return true if the phase \a p has valid thermo data for
549  //! the current temperature.
550  /*!
551  * @param p Index of the phase.
552  */
553  bool tempOK(index_t p) const;
554 
555  // These methods are meant for internal use.
556 
557  //! Update the locally-stored composition within this object
558  //! to match the current compositions of the phase objects.
559  /*!
560  *
561  * @deprecated 'update' is confusing within this context.
562  * Switching to the terminology 'uploadFrom'
563  * and 'downloadTo'. uploadFrom means to
564  * query the underlying ThermoPhase objects and
565  * fill in the resulting information within
566  * this object. downloadTo means to take information
567  * from this object and put it into the underlying
568  * ThermoPhase objects.
569  * switch to uploadMoleFractionsFromPhases();
570  */
571  DEPRECATED(void updateMoleFractions());
572 
573  //! Update the locally-stored composition within this object
574  //! to match the current compositions of the phase objects.
575  /*!
576  * Query the underlying ThermoPhase objects for their mole
577  * fractions and fill in the mole fraction vector of this
578  * current object. Adjust element compositions within this
579  * object to match.
580  *
581  * This is an upload operation in the sense that we are taking
582  * downstream information (ThermoPhase object info) and
583  * applying it to an upstream object (MultiPhase object).
584  */
586 
587  //! Set the states of the phase objects to the locally-stored
588  //! state within this MultiPhase object.
589  /*!
590  *
591  * Note that if individual phases have T and P different
592  * than that stored locally, the phase T and P will be modified.
593  *
594  * This is an download operation in the sense that we are taking
595  * upstream object information (MultiPhase object) and
596  * applying it to downstream objects (ThermoPhase object information)
597  *
598  * Therefore, the term, "update", is appropriate for a downstream
599  * operation.
600  */
601  void updatePhases() const;
602 
603 private:
604  //! Calculate the element abundance vector
605  void calcElemAbundances() const;
606 
607 
608  //! Vector of the number of moles in each phase.
609  /*!
610  * Length = m_np, number of phases.
611  */
613 
614  /**
615  * Vector of the ThermoPhase Pointers.
616  */
617  std::vector<ThermoPhase*> m_phase;
618 
619  //! Global Stoichiometric Coefficient array
620  /*!
621  * This is a two dimensional array m_atoms(m, k). The first
622  * index is the global element index. The second index, k, is the
623  * global species index.
624  * The value is the number of atoms of type m in species k.
625  */
627 
628  /**
629  * Locally stored vector of mole fractions of all species
630  * comprising the MultiPhase object.
631  */
633 
634  //! Mapping between the global species number and the phase ID
635  /*!
636  * m_spphase[kGlobal] = iPhase
637  * Length = number of global species
638  */
639  std::vector<size_t> m_spphase;
640 
641  //! Vector of ints containing of first species index in the global list of species
642  //! for each phase
643  /*!
644  * kfirst = m_spstart[ip], kfirst is the index of the first species in the ip'th
645  * phase.
646  */
647  std::vector<size_t> m_spstart;
648 
649  //! String names of the global elements
650  /*!
651  * This has a length equal to the number of global elements.
652  */
653  std::vector<std::string> m_enames;
654 
655  //! Atomic number of each element
656  /*!
657  * This is the atomic number of each global element.
658  */
660 
661  //! Vector of species names in the problem
662  /*!
663  * Vector is over all species defined in the object,
664  * the global species index.
665  */
666  std::vector<std::string> m_snames;
667 
668  //! Returns the global element index, given the element string name
669  /*!
670  * -> used in the construction. However, wonder if it needs to be global.
671  */
672  std::map<std::string, size_t> m_enamemap;
673 
674  /**
675  * Number of phases in the MultiPhase object
676  */
678 
679  //! Current value of the temperature (kelvin)
680  doublereal m_temp;
681 
682  //! Current value of the pressure (Pa)
683  doublereal m_press;
684 
685  /**
686  * Number of distinct elements in all of the phases
687  */
689  /**
690  * Number of distinct species in all of the phases
691  */
693 
694  //! True if the init() routine has been called, and the MultiPhase frozen
695  bool m_init;
696 
697  //! Global ID of the element corresponding to the electronic charge.
698  /*!
699  * If there is none, then this is equal to -1
700  */
701  size_t m_eloc;
702 
703  //! Vector of bools indicating whether temperatures are ok for phases.
704  /*!
705  * If the current temperature is outside the range of valid temperatures
706  * for the phase thermodynamics, the phase flag is set to false.
707  */
708  mutable std::vector<bool> m_temp_OK;
709 
710  //! Minimum temperature for which thermo parameterizations are valid
711  /*!
712  * Stoichiometric phases are ignored in this determination.
713  * units Kelvin
714  */
715  doublereal m_Tmin;
716 
717  //! Minimum temperature for which thermo parameterizations are valid
718  /*!
719  * Stoichiometric phases are ignored in this determination.
720  * units Kelvin
721  */
722  doublereal m_Tmax;
723 
724  //! Vector of element abundances
725  /*!
726  * m_elemAbundances[mGlobal] = kmol of element mGlobal summed over all
727  * species in all phases.
728  */
730 };
731 
732 //! Function to output a MultiPhase description to a stream
733 /*!
734  * Writes out a description of the contents of each phase of the
735  * MultiPhase using the report function.
736  *
737  * @param s ostream
738  * @param x Reference to a MultiPhase
739  * @return returns a reference to the ostream
740  */
741 inline std::ostream& operator<<(std::ostream& s, Cantera::MultiPhase& x)
742 {
743  size_t ip;
744  for (ip = 0; ip < x.nPhases(); ip++) {
745  if (x.phase(ip).name() != "") {
746  s << "*************** " << x.phase(ip).name() << " *****************" << std::endl;
747  } else {
748  s << "*************** Phase " << ip << " *****************" << std::endl;
749  }
750  s << "Moles: " << x.phaseMoles(ip) << std::endl;
751 
752  s << x.phase(ip).report() << std::endl;
753  }
754  return s;
755 }
756 
757 //! Choose the optimum basis of species for the equilibrium calculations.
758 /*!
759  * This is done by
760  * choosing the species with the largest mole fraction
761  * not currently a linear combination of the previous components.
762  * Then, calculate the stoichiometric coefficient matrix for that
763  * basis.
764  *
765  * Calculates the identity of the component species in the mechanism.
766  * Rearranges the solution data to put the component data at the
767  * front of the species list.
768  *
769  * Then, calculates SC(J,I) the formation reactions for all noncomponent
770  * species in the mechanism.
771  *
772  * Input
773  * ---------
774  * @param mphase Pointer to the multiphase object. Contains the
775  * species mole fractions, which are used to pick the
776  * current optimal species component basis.
777  * @param orderVectorElements
778  * Order vector for the elements. The element rows
779  * in the formula matrix are
780  * rearranged according to this vector.
781  * @param orderVectorSpecies
782  * Order vector for the species. The species are
783  * rearranged according to this formula. The first
784  * nCompoments of this vector contain the calculated
785  * species components on exit.
786  * @param doFormRxn If true, the routine calculates the formation
787  * reaction matrix based on the calculated
788  * component species. If false, this step is skipped.
789  *
790  * Output
791  * ---------
792  * @param usedZeroedSpecies = If true, then a species with a zero concentration
793  * was used as a component. The problem may be
794  * converged.
795  * @param formRxnMatrix
796  *
797  * @return Returns the number of components.
798  *
799  * @ingroup equilfunctions
800  */
801 size_t BasisOptimize(int* usedZeroedSpecies, bool doFormRxn,
802  MultiPhase* mphase, std::vector<size_t>& orderVectorSpecies,
803  std::vector<size_t>& orderVectorElements,
804  vector_fp& formRxnMatrix);
805 
806 //! This subroutine handles the potential rearrangement of the constraint
807 //! equations represented by the Formula Matrix.
808 /*!
809  * Rearrangement is only
810  * necessary when the number of components is less than the number of
811  * elements. For this case, some constraints can never be satisfied
812  * exactly, because the range space represented by the Formula
813  * Matrix of the components can't span the extra space. These
814  * constraints, which are out of the range space of the component
815  * Formula matrix entries, are migrated to the back of the Formula
816  * matrix.
817  *
818  * A prototypical example is an extra element column in
819  * FormulaMatrix[],
820  * which is identically zero. For example, let's say that argon is
821  * has an element column in FormulaMatrix[], but no species in the
822  * mechanism
823  * actually contains argon. Then, nc < ne. Unless the entry for
824  * desired element abundance vector for Ar is zero, then this
825  * element abundance constraint can never be satisfied. The
826  * constraint vector is not in the range space of the formula
827  * matrix.
828  * Also, without perturbation
829  * of FormulaMatrix[], BasisOptimize[] would produce a zero pivot
830  * because the matrix
831  * would be singular (unless the argon element column was already the
832  * last column of FormulaMatrix[].
833  * This routine borrows heavily from BasisOptimize algorithm. It
834  * finds nc constraints which span the range space of the Component
835  * Formula matrix, and assigns them as the first nc components in the
836  * formula matrix. This guarantees that BasisOptimize has a
837  * nonsingular matrix to invert.
838  * input
839  * @param nComponents Number of components calculated previously.
840  *
841  * @param elementAbundances Current value of the element abundances
842  *
843  * @param mphase Input pointer to a MultiPhase object
844  *
845  * @param orderVectorSpecies input vector containing the ordering
846  * of the global species in mphase. This is used
847  * to extract the component basis of the mphase object.
848  *
849  * output
850  * @param orderVectorElements Output vector containing the order
851  * of the elements that is necessary for
852  * calculation of the formula matrix.
853  *
854  * @ingroup equilfunctions
855  */
856 size_t ElemRearrange(size_t nComponents, const vector_fp& elementAbundances,
857  MultiPhase* mphase,
858  std::vector<size_t>& orderVectorSpecies,
859  std::vector<size_t>& orderVectorElements);
860 
861 #ifdef DEBUG_MODE
862 //! External int that is used to turn on debug printing for the
863 //! BasisOptimze program.
864 /*!
865  * Set this to 1 if you want debug printing from BasisOptimize.
866  */
867 extern int BasisOptimize_print_lvl;
868 #endif
869 }
870 
871 #endif