Cantera  2.3.0
importKinetics.cpp
Go to the documentation of this file.
1 /**
2  * @file importKinetics.cpp
3  * Declarations of global routines for the importing
4  * of kinetics data from XML files (see \ref inputfiles).
5  *
6  * This file contains routines which are global routines, i.e.,
7  * not part of any object. These routine take as input, ctml
8  * pointers to data, and pointers to %Cantera objects. The purpose
9  * of these routines is to initialize the %Cantera objects with data
10  * from the ctml tree structures.
11  */
12 
13 // This file is part of Cantera. See License.txt in the top-level directory or
14 // at http://www.cantera.org/license.txt for license and copyright information.
15 
20 #include "cantera/base/ctml.h"
21 
22 #include <cstring>
23 
24 using namespace std;
25 
26 namespace Cantera
27 {
28 
30  std::string default_phase, bool check_for_duplicates)
31 {
32  int itot = 0;
33 
34  // Search the children of the phase element for the XML element named
35  // reactionArray. If we can't find it, then return signaling having not
36  // found any reactions. Apparently, we allow multiple reactionArray elements
37  // here Each one will be processed sequentially, with the end result being
38  // purely additive.
39  vector<XML_Node*> rarrays = p.getChildren("reactionArray");
40  if (rarrays.empty()) {
41  return false;
42  }
43  for (size_t n = 0; n < rarrays.size(); n++) {
44  // Go get a reference to the current XML element, reactionArray. We will
45  // process this element now.
46  const XML_Node& rxns = *rarrays[n];
47 
48  // The reactionArray element has an attribute called, datasrc. The value
49  // of the attribute is the XML element comprising the top of the tree of
50  // reactions for the phase. Find this datasrc element starting with the
51  // root of the current XML node.
52  const XML_Node* rdata = get_XML_Node(rxns["datasrc"], &rxns.root());
53 
54  // If the reactionArray element has a child element named "skip", and if
55  // the attribute of skip called "species" has a value of "undeclared",
56  // we will set rxnrule.skipUndeclaredSpecies to 'true'. rxnrule is
57  // passed to the routine that parses each individual reaction so that
58  // the parser will skip all reactions containing an undefined species
59  // without throwing an error.
60  //
61  // Similarly, an attribute named "third_bodies" with the value of
62  // "undeclared" will skip undeclared third body efficiencies (while
63  // retaining the reaction and any other efficiencies).
64  if (rxns.hasChild("skip")) {
65  const XML_Node& sk = rxns.child("skip");
66  if (sk["species"] == "undeclared") {
67  kin.skipUndeclaredSpecies(true);
68  }
69  if (sk["third_bodies"] == "undeclared") {
70  kin.skipUndeclaredThirdBodies(true);
71  }
72  }
73 
74  // Search for child elements called include. We only include a reaction
75  // if it's tagged by one of the include fields. Or, we include all
76  // reactions if there are no include fields.
77  vector<XML_Node*> incl = rxns.getChildren("include");
78  vector<XML_Node*> allrxns = rdata->getChildren("reaction");
79  // if no 'include' directive, then include all reactions
80  if (incl.empty()) {
81  for (size_t i = 0; i < allrxns.size(); i++) {
82  kin.addReaction(newReaction(*allrxns[i]));
83  ++itot;
84  }
85  } else {
86  for (size_t nii = 0; nii < incl.size(); nii++) {
87  const XML_Node& ii = *incl[nii];
88  string imin = ii["min"];
89  string imax = ii["max"];
90 
91  string::size_type iwild = string::npos;
92  if (imax == imin) {
93  iwild = imin.find("*");
94  if (iwild != string::npos) {
95  imin = imin.substr(0,iwild);
96  imax = imin;
97  }
98  }
99 
100  for (size_t i = 0; i < allrxns.size(); i++) {
101  const XML_Node* r = allrxns[i];
102  string rxid;
103  if (r) {
104  rxid = r->attrib("id");
105  if (iwild != string::npos) {
106  rxid = rxid.substr(0,iwild);
107  }
108 
109  // To decide whether the reaction is included or not we
110  // do a lexical min max and operation. This sometimes
111  // has surprising results.
112  if ((rxid >= imin) && (rxid <= imax)) {
113  kin.addReaction(newReaction(*r));
114  ++itot;
115  }
116  }
117  }
118  }
119  }
120  }
121 
122  if (check_for_duplicates) {
123  kin.checkDuplicates();
124  }
125 
126  return true;
127 }
128 
129 bool importKinetics(const XML_Node& phase, std::vector<ThermoPhase*> th,
130  Kinetics* k)
131 {
132  if (k == 0) {
133  return false;
134  }
135 
136  // This phase will be the owning phase for the kinetics operator
137  // For interfaces, it is the surface phase between two volumes.
138  // For homogeneous kinetics, it's the current volumetric phase.
139  string owning_phase = phase["id"];
140 
141  bool check_for_duplicates = false;
142  if (phase.parent() && phase.parent()->hasChild("validate")) {
143  const XML_Node& d = phase.parent()->child("validate");
144  if (d["reactions"] == "yes") {
145  check_for_duplicates = true;
146  }
147  }
148 
149  // if other phases are involved in the reaction mechanism, they must be
150  // listed in a 'phaseArray' child element. Homogeneous mechanisms do not
151  // need to include a phaseArray element.
152  vector<string> phase_ids;
153  if (phase.hasChild("phaseArray")) {
154  const XML_Node& pa = phase.child("phaseArray");
155  getStringArray(pa, phase_ids);
156  }
157  phase_ids.push_back(owning_phase);
158 
159  // for each referenced phase, attempt to find its id among those
160  // phases specified.
161  string msg = "";
162  for (size_t n = 0; n < phase_ids.size(); n++) {
163  string phase_id = phase_ids[n];
164  bool phase_ok = false;
165  // loop over the supplied 'ThermoPhase' objects representing
166  // phases, to find an object with the same id.
167  for (size_t m = 0; m < th.size(); m++) {
168  if (th[m]->id() == phase_id) {
169  phase_ok = true;
170  // if no phase with this id has been added to
171  //the kinetics manager yet, then add this one
172  if (k->phaseIndex(phase_id) == npos) {
173  k->addPhase(*th[m]);
174  }
175  }
176  msg += " "+th[m]->id();
177  }
178  if (!phase_ok) {
179  throw CanteraError("importKinetics",
180  "phase "+phase_id+" not found. Supplied phases are:"+msg);
181  }
182  }
183 
184  // allocates arrays, etc. Must be called after the phases have been added to
185  // 'kin', so that the number of species in each phase is known.
186  k->init();
187 
188  // Install the reactions.
189  return installReactionArrays(phase, *k, owning_phase, check_for_duplicates);
190 }
191 
192 bool buildSolutionFromXML(XML_Node& root, const std::string& id,
193  const std::string& nm, ThermoPhase* th, Kinetics* kin)
194 {
195  XML_Node* x = get_XML_NameID(nm, string("#")+id, &root);
196  if (!x) {
197  return false;
198  }
199 
200  // Fill in the ThermoPhase object by querying the const XML_Node tree
201  // located at x.
202  importPhase(*x, th);
203 
204  // Create a vector of ThermoPhase pointers of length 1 having the current th
205  // ThermoPhase as the entry.
206  std::vector<ThermoPhase*> phases{th};
207 
208  // Fill in the kinetics object k, by querying the const XML_Node tree
209  // located by x. The source terms and eventually the source term vector will
210  // be constructed from the list of ThermoPhases in the vector, phases.
211  importKinetics(*x, phases, kin);
212  return true;
213 }
214 
215 }
XML_Node * get_XML_Node(const std::string &file_ID, XML_Node *root)
This routine will locate an XML node in either the input XML tree or in another input file specified ...
Definition: global.cpp:214
std::vector< XML_Node * > getChildren(const std::string &name) const
Get a vector of pointers to XML_Node containing all of the children of the current node which match t...
Definition: xml.cpp:864
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data...
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:165
Headers for the factory class that can create known ThermoPhase objects (see Thermodynamic Properties...
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:97
virtual bool addReaction(shared_ptr< Reaction > r)
Add a single reaction to the mechanism.
Definition: Kinetics.cpp:522
STL namespace.
bool installReactionArrays(const XML_Node &p, Kinetics &kin, std::string default_phase, bool check_for_duplicates)
Install information about reactions into the kinetics object, kin.
Base class for a phase with thermodynamic properties.
Definition: ThermoPhase.h:93
virtual void init()
Prepare the class for the addition of reactions, after all phases have been added.
Definition: Kinetics.h:743
bool importKinetics(const XML_Node &phase, std::vector< ThermoPhase *> th, Kinetics *k)
Import a reaction mechanism for a phase or an interface.
Public interface for kinetics managers.
Definition: Kinetics.h:111
XML_Node * parent() const
Returns a pointer to the parent node of the current node.
Definition: xml.cpp:525
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:65
shared_ptr< Reaction > newReaction(const XML_Node &rxn_node)
Create a new Reaction object for the reaction defined in rxn_node
Definition: Reaction.cpp:604
virtual std::pair< size_t, size_t > checkDuplicates(bool throw_err=true) const
Check for duplicate reactions.
Definition: Kinetics.cpp:154
void importPhase(XML_Node &phase, ThermoPhase *th)
Import a phase information into an empty ThermoPhase object.
bool buildSolutionFromXML(XML_Node &root, const std::string &id, const std::string &nm, ThermoPhase *th, Kinetics *kin)
Build a single-phase ThermoPhase object with associated kinetics mechanism.
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
Definition: xml.cpp:536
XML_Node & child(const size_t n) const
Return a changeable reference to the n&#39;th child of the current node.
Definition: xml.cpp:546
XML_Node & root() const
Return the root of the current XML_Node tree.
Definition: xml.cpp:1025
Definitions of global routines for the importing of data from XML files (see Input File Handling)...
std::string attrib(const std::string &attr) const
Function returns the value of an attribute.
Definition: xml.cpp:500
void getStringArray(const XML_Node &node, std::vector< std::string > &v)
This function interprets the value portion of an XML element as a string.
Definition: ctml.cpp:470
Contains declarations for string manipulation functions within Cantera.
Namespace for the Cantera kernel.
Definition: application.cpp:29
virtual void addPhase(thermo_t &thermo)
Add a phase to the kinetics manager object.
Definition: Kinetics.cpp:485
void skipUndeclaredThirdBodies(bool skip)
Determine behavior when adding a new reaction that contains third-body efficiencies for species not d...
Definition: Kinetics.h:801
XML_Node * get_XML_NameID(const std::string &nameTarget, const std::string &file_ID, XML_Node *root)
This routine will locate an XML node in either the input XML tree or in another input file specified ...
Definition: global.cpp:252
size_t phaseIndex(const std::string &ph)
Return the phase index of a phase in the list of phases defined within the object.
Definition: Kinetics.h:238
void skipUndeclaredSpecies(bool skip)
Determine behavior when adding a new reaction that contains species not defined in any of the phases ...
Definition: Kinetics.h:792