cantera/Cantera/src/base/ctml.h
2009-01-09 16:52:55 +00:00

635 lines
23 KiB
C++
Executable file

/**
* @file ctml.h
* CTML ("Cantera Markup Language") is the variant of XML that Cantera uses
* to store data. These functions read and write it.
* (see \ref inputfiles and importCTML, ck2ctml)
*/
/*
* $Revision$
* $Date$
*/
// Copyright 2002 California Institute of Technology
#ifndef CT_CTML_H
#define CT_CTML_H
#include "ct_defs.h"
#include "xml.h"
#include "Array.h"
//! The ctml namespace adds functionality to the XML object, by providing
//! standard functions that read and write and interpret XML files and object trees.
namespace ctml {
//! const Specifying the CTML version number
/*!
* @todo Codify what the CTML_Version number means.
*/
const std::string CTML_Version = "1.4.1";
// bool isBuiltin(std::string nm);
//! This function adds a child node with the name, "bool", with a value
//! consisting of a single bool
/*!
* This function will add a child node to the current XML node, with the
* name "bool". It will have a title attribute, and the body
* of the XML node will be filled out with a single bool.
*
* Example:
*
* Code snipet:
* @verbatum
const XML_Node &node;
std::string titleString = "doSpecialOp";
bool value = true;
addBool(node, titleString, value);
@endverbatum
*
* Creates the following the snippet in the XML file:
* @verbatum
<parentNode>
<bool title="doSpecialOp" type="optional">
true
<\integer>
<\parentNode>
@endverbatum
*
* @param node reference to the XML_Node object of the parent XML element
* @param titleString String name of the title attribute
* @param value Value - single bool
*
* @todo I don't think this is used. Figure out what is used for writing bools,
* and codify that.
*/
void addBool(Cantera::XML_Node& node, const std::string &title,
const bool value);
//! This function adds a child node with the name, "integer", with a value
//! consisting of a single integer
/*!
* This function will add a child node to the current XML node, with the
* name "integer". It will have a title attribute, and the body
* of the XML node will be filled out with a single integer
*
* Example:
*
* Code snipet:
* @verbatum
const XML_Node &node;
std::string titleString = "maxIterations";
int value = 1000;
std::string typeString = "optional";
std::string units = "";
addInteger(node, titleString, value, typeString, units);
@endverbatum
*
* Creates the following the snippet in the XML file:
* @verbatum
<parentNode>
<integer title="maxIterations" type="optional">
100
<\integer>
<\parentNode>
@endverbatum
*
* @param node reference to the XML_Node object of the parent XML element
* @param titleString String name of the title attribute
* @param value Value - single integer
* @param unitsString String name of the Units attribute. The default is to
* have an empty string.
* @param typeString String type. This is an optional parameter. The default
* is to have an empty string.
*
* @todo I don't think this is used. Figure out what is used for writing integers,
* and codify that. unitsString shouldn't be here, since it's an int.
* typeString should be codified as to its usage.
*/
void addInteger(Cantera::XML_Node& node, const std::string &titleString,
const int value, const std::string unitsString="",
const std::string typeString="");
//! This function adds a child node with the name, "float", with a value
//! consisting of a single floating point number
/*!
* This function will add a child node to the current XML node, with the
* name "float". It will have a title attribute, and the body
* of the XML node will be filled out with a single float
*
* Example:
*
* Code snipet:
* @verbatum
const XML_Node &node;
std::string titleString = "activationEnergy";
double value = 50.3;
doublereal maxval = 1.0E3;
doublereal minval = 0.0;
std::string typeString = "optional";
std::string unitsString = "kcal/gmol";
addFloat(node, titleString, value, unitsString, typeString, minval, maxval);
@endverbatum
*
* Creates the following the snippet in the XML file:
* @verbatum
<parentNode>
<float title="activationEnergy" type="optional" units="kcal/gmol" min="0.0" max="1.0E3">
50.3
<\float>
<\parentNode>
@endverbatum
*
* @param node reference to the XML_Node object of the parent XML element
* @param titleString String name of the title attribute
* @param value Value - single integer
* @param unitsString String name of the Units attribute. The default is to
* have an empty string.
* @param typeString String type. This is an optional parameter. The default
* is to have an empty string.
* @param minval Minimum allowed value of the float. The default is the
* special double, Cantera::Undef, which means to ignore the
* entry.
* @param maxval Maximum allowed value of the float. The default is the
* special double, Cantera::Undef, which means to ignore the
* entry.
*
* @todo I don't think this is used. Figure out what is used for writing floats,
* and codify that. minval and maxval should be codified.
* typeString should be codified as to its usage.
*/
void addFloat(Cantera::XML_Node& node, const std::string &titleString,
const doublereal value, const std::string unitsString="",
const std::string typeString="", const doublereal minval = Cantera::Undef,
const doublereal maxval = Cantera::Undef);
//! This function adds a child node with the name, "intArray", with a value
//! consisting of a comma separated list of integers
/*!
* This function will add a child node to the current XML node, with the
* name "intArray". It will have a title attribute, and the body
* of the XML node will be filled out with a comma separated list of
* integers
*
* Example:
*
* Code snipet:
* @verbatum
const XML_Node &node;
std::string titleString = "additionalCases";
int n = 3;
int cases[3] = [3, 6, 10];
std::string typeString = "optional";
std::string units = "";
addIntegerArray(node, titleString, n, &cases[0], typeString, units);
@endverbatum
*
* Creates the following the snippet in the XML file:
* @verbatum
<parentNode>
<intArray title="additionalCases" type="optional">
3, 6, 10
<\intArray>
<\parentNode>
@endverbatum
*
* @param node reference to the XML_Node object of the parent XML element
* @param titleString String name of the title attribute
* @param n Length of the integer vector.
* @param values Pointer to a vector of integers
* @param unitsString String name of the Units attribute. This is an optional
* parameter. The default is to
* have an empty string.
* @param typeString String type. This is an optional parameter. The default
* is to have an empty string.
* @param minval Minimum allowed value of the int. This is an optional
* parameter. The default is the
* special double, Cantera::Undef, which means to ignore the
* entry.
* @param maxval Maximum allowed value of the int. This is an optional
* parameter. The default is the
* special double, Cantera::Undef, which means to ignore the
* entry.
*
* @todo I don't think this is used. Figure out what is used for writing integers,
* and codify that. unitsString shouldn't be here, since it's an int.
* typeString should be codified as to its usage.
*/
void addIntegerArray(Cantera::XML_Node& node, const std::string &titleString,
const int n, const int* const values,
const std::string unitsString="", const std::string typeString="",
const doublereal minval=Cantera::Undef,
const doublereal maxval=Cantera::Undef);
//! This function adds a child node with the name, "floatArray", with a value
//! consisting of a comma separated list of floats
/*!
* This function will add a child node to the current XML node, with the
* name "floatArray". It will have a title attribute, and the body
* of the XML node will be filled out with a comma separated list of
* integers
*
* Example:
*
* Code snipet:
* @verbatum
const XML_Node &node;
std::string titleString = "additionalTemperatures";
int n = 3;
int Tcases[3] = [273.15, 298.15, 373.15];
std::string typeString = "optional";
std::string units = "Kelvin";
addFloatArray(node, titleString, n, &cases[0], typeString, units);
@endverbatum
*
* Creates the following the snippet in the XML file:
* @verbatum
<parentNode>
<floatArray title="additionalTemperatures" type="optional" units="Kelvin">
273.15, 298.15, 373.15
<\floatArray>
<\parentNode>
@endverbatum
*
* @param node reference to the XML_Node object of the parent XML element
* @param titleString String name of the title attribute
* @param n Length of the doubles vector.
* @param values Pointer to a vector of doubles
* @param unitsString String name of the Units attribute. This is an optional
* parameter. The default is to
* have an empty string.
* @param typeString String type. This is an optional parameter. The default
* is to have an empty string.
* @param minval Minimum allowed value of the int. This is an optional
* parameter. The default is the
* special double, Cantera::Undef, which means to ignore the
* entry.
* @param maxval Maximum allowed value of the int. This is an optional
* parameter. The default is the
* special double, Cantera::Undef, which means to ignore the
* entry.
*
* @todo I don't think this is used. Figure out what is used for writing integers,
* and codify that. unitsString shouldn't be here, since it's an int.
* typeString should be codified as to its usage.
*/
void addFloatArray(Cantera::XML_Node& node, const std::string &titleString,
const int n, const doublereal* const values,
const std::string unitsString="", const std::string typeString="",
const doublereal minval = Cantera::Undef,
const doublereal maxval = Cantera::Undef);
//! This function adds a child node with the name string with a string value
//! to the current node
/*!
* This function will add a child node to the current XML node, with the
* name "string". It will have a title attribute, and the body
* of the XML node will be filled out with the valueString argument verbatim.
*
* Example:
*
* Code snipet:
* @verbatum
const XML_Node &node;
addString(XML_Node& node, std::string titleString, std::string valueString,
std::string typeString);
@endverbatum
*
* Creates the following the snippet in the XML file:
* @verbatum
<string title="titleString" type="typeString">
valueString
<\string>
@endverbatum
*
* @param node reference to the XML_Node object of the parent XML element
* @param valueString Value string to be used in the new XML node.
* @param titleString String name of the title attribute
* @param typeString String type. This is an optional parameter.
*/
void addString(Cantera::XML_Node& node, const std::string &titleString,
const std::string &valueString, const std::string typeString="");
void getFloatArray(const Cantera::XML_Node& node, Cantera::vector_fp& v,
bool convert=true, std::string type="",
std::string nodeName = "floatArray");
void getStringArray(const Cantera::XML_Node& node, std::vector<std::string>& v);
void getStringArray(const std::string& val, std::vector<std::string>& v);
void getMap(const Cantera::XML_Node& node, std::map<std::string, std::string>& m);
//! This function interprets the value portion of an XML element
//! as a series of "Pairs" separated by white space.
/*!
* Each pair consists of nonwhite-space characters.
* The first ":" found in the pair string is used to separate
* the string into two parts. The first part is called the "key"
* The second part is called the "val".
* String vectors of key[i] and val[i] are returned in the
* argument list.
* Warning: No spaces are allowed in each pair. Quotes are part
* of the string.
* Example: @verbatum
* <xmlNode>
red:112 blue:34
green:banana
</xmlNode> @endverbatum
*
* Returns:
* key val
* 0: "red" "112"
* 1: "blue" "34"
* 2: "green" "banana"
*/
void getPairs(const Cantera::XML_Node& node, std::vector<std::string>& key,
std::vector<std::string>& val);
void getMatrixValues(const Cantera::XML_Node& node,
const std::vector<std::string>& keyString1,
const std::vector<std::string>& keyString2,
Cantera::Array2D &returnValues, bool convert = true,
bool matrixSymmetric = false);
//! Get a vector of integer values from a child element.
/*!
* Returns a std::map containing a keyed values for child XML_Nodes
* of the current node with the name, "integer".
* In the keyed mapping there will be a list of titles vs. values
* for all of the XML nodes.
* The integer XML_nodes are expected to be in a particular form created
* by the function addInteger(). One value per XML_node is expected.
*
*
* Example:
*
* Code snipet:
* @verbatum
const XML_Node &State_XMLNode;
std::map<std::string, integer> v;
getinteger(State_XMLNode, v);
@endverbatum
*
* reads the corresponding XML file:
*
* @verbatum
<state>
<integer title="i1"> 1 <\integer>
<integer title="i2"> 2 <\integer>
<integer title="i3"> 3 <\integer>
<\state>
@endverbatum
*
* Will produce the mapping:
*
* v["i1"] = 1
* v["i2"] = 2
* v["i3"] = 3
*
*
* @param node Current XML node to get the values from
* @param v Output map of the results.
*/
void getIntegers(const Cantera::XML_Node& node, std::map<std::string,int>& v);
//! Get a floating-point value from a child element.
/*!
* Returns a double value for the child named 'name' of element 'parent'. If
* 'type' is supplied and matches a known unit type, unit
* conversion to SI will be done if the child element has an attribute
* 'units'.
*
* Note, it's an error for the child element not to exist.
*
* Example:
*
* Code snipet:
* @verbatum
const XML_Node &State_XMLNode;
doublereal pres = OneAtm;
if (state_XMLNode.hasChild("pressure")) {
pres = getFloat(State_XMLNode, "pressure", "toSI");
}
@endverbatum
*
* reads the corresponding XML file:
* @verbatum
<state>
<pressure units="Pa"> 101325.0 </pressure>
<\state>
@endverbatum
*
* @param parent reference to the XML_Node object of the parent XML element
* @param name Name of the XML child element
* @param type String type. Currently known types are "toSI" and "actEnergy",
* and "" , for no conversion. The default value is "",
* which implies that no conversion is allowed.
*/
doublereal getFloat(const Cantera::XML_Node& parent, std::string name,
std::string type="");
//! Get a vector of floating-point values from a child element.
/*!
* Returns a std::map containing a keyed values for child XML_Nodes
* of the current node with the name, "float".
* In the keyed mapping there will be a list of titles vs. values
* for all of the XML nodes.
* The float XML_nodes are expected to be in a particular form created
* by the function addFloat(). One value per XML_node is expected.
*
*
* Example:
*
* Code snipet:
* @verbatum
const XML_Node &State_XMLNode;
std::map<std::string,double> v;
bool convert = true;
getFloats(State_XMLNode, v, convert);
@endverbatum
*
* reads the corresponding XML file:
*
* @verbatum
<state>
<float title="a1" units="m3"> 32.4 <\float>
<float title="a2" units="cm3"> 1. <\float>
<float title="a3"> 100. <\float>
<\state>
@endverbatum
*
* Will produce the mapping:
*
* v["a1"] = 32.4
* v["a2"] = 1.0E-6
* v["a3"] = 100.
*
*
* @param node Current XML node to get the values from
* @param v Output map of the results.
* @param convert Turn on conversion to SI units
*/
void getFloats(const Cantera::XML_Node& node, std::map<std::string, double>& v,
const bool convert=true);
//! Get a floating-point value from a child element with a defined units field
/*!
* Returns a double value for the child named 'name' of element 'parent'.
* 'type' must be supplied and match a known unit type.
*
* Note, it's an error for the child element not to exist.
*
* Example:
*
* Code snipet:
* @verbatum
const XML_Node &State_XMLNode;
doublereal pres = OneAtm;
if (state_XMLNode.hasChild("pressure")) {
pres = getFloatDefaultUnits(State_XMLNode, "pressure", "Pa", "toSI");
}
@endverbatum
*
* reads the corresponding XML file:
* @verbatum
<state>
<pressure units="Pa"> 101325.0 </pressure>
<\state>
@endverbatum
*
* @param parent reference to the XML_Node object of the parent XML element
* @param name Name of the XML child element
* @param defaultUnits Default units string to be found in the units attribute.
* If the units string in the XML field is equal to defaultUnits,
* no units conversion will be carried out.
* @param type String type. Currently known types are "toSI" and "actEnergy",
* and "" , for no conversion. The default value is "",
* which implies that no conversion is allowed.
*/
doublereal getFloatDefaultUnits(const Cantera::XML_Node& parent, std::string name,
std::string defaultUnits, std::string type="toSI");
//! Get an integer value from a child element.
/*!
* Returns an integer value for the child named 'name' of element 'parent'.
*
* Note, it's an error for the child element not to exist.
*
* Example:
*
* Code snipet:
* @verbatum
const XML_Node &State_XMLNode;
int number = 1;
if (state_XMLNode.hasChild("NumProcs")) {
number = getInteger(State_XMLNode, "numProcs");
}
@endverbatum
*
* reads the corresponding XML file:
* @verbatum
<state>
<numProcs> 10 <numProcs/>
<\state>
@endverbatum
*
* @param parent reference to the XML_Node object of the parent XML element
* @param name Name of the XML child element
*/
int getInteger(const Cantera::XML_Node& parent, std::string name);
void getFunction(const Cantera::XML_Node& node, std::string& type,
doublereal& xmin, doublereal& xmax, Cantera::vector_fp& coeffs);
//! Search the child nodes of the current node for an XML Node with a Title
//! attribute of a given name.
/*!
* @param node Current node from which to conduct the search
* @param title Name of the title attribute
*
* @return Returns a pointer to the matched child node. Returns 0 if no node is
* found.
*/
Cantera::XML_Node* getByTitle(const Cantera::XML_Node& node, const std::string &title);
//! This function reads a child node with the name string with a specific
//! title attribute named titleString
/*!
* This function will read a child node to the current XML node, with the
* name "string". It must have a title attribute, named titleString, and the body
* of the XML node will be read into the valueString output argument.
*
* If the child node is not found then the empty string is returned.
*
* Example:
*
* Code snipet:
* @verbatum
const XML_Node &node;
getString(XML_Node& node, std::string titleString, std::string valueString,
std::string typeString);
@endverbatum
*
* Reads the following the snippet in the XML file:
* @verbatum
<string title="titleString" type="typeString">
valueString
<\string>
@endverbatum
*
* @param node reference to the XML_Node object of the parent XML element
* @param titleString String name of the title attribute of the child node
* @param valueString Value string that is found in the child node. output variable
* @param typeString String type. This is an optional output variable
*/
void getString(const Cantera::XML_Node& node, const std::string &titleString,
std::string& valueString, std::string& typeString);
//! This function reads a child node with the name, nameString, and returns
//! its xml value as the return string
/*!
* If the child XML_node named "name" doesn't exist, the empty string is returned.
*
* Code snipet:
* @verbatum
const XML_Node &parent;
string nameString = "vacency_species";
string valueString = getChildValue(parent, nameString
std::string typeString);
@endverbatum
*
* returns valueString = "O(V)"
*
* from the following the snippet in the XML file:
*
* @verbatum
<vacencySpecies>
O(V)
<\vancencySpecies>
@endverbatum
*
* @param parent parent reference to the XML_Node object of the parent XML element
* @param nameString Name of the childe XML_Node to read the value from.
*
* @return String value of the child XML_Node
*/
std::string getChildValue(const Cantera::XML_Node& parent, const std::string &nameString);
// These are defined in ct2ctml.cpp
void get_CTML_Tree(Cantera::XML_Node* node, std::string file, int debug = 0);
//! Convert a cti file into a ctml file
/*!
*
* @ingroup inputfiles
*/
void ct2ctml(const char* file, int debug = 0);
}
#endif