From e4aa6aa28270d83b96362a77c395640b6331df1a Mon Sep 17 00:00:00 2001 From: Harry Moffat Date: Thu, 28 Jul 2005 21:53:05 +0000 Subject: [PATCH] Added the getMatrixValues routine. This routine fills in a matrix of doubles, keyed by a lookup name that determines the two indecises, e.g.: H+:Cl-:3.0E5 This introduces a triplet notation into the Cantera API. Added a parameter to the getFloatArray() routine, that has a default value -> so it shouldn't cause any changes to the API. --- Cantera/src/ctml.cpp | 187 ++++++++++++++++++++++++++++++++++++++++--- Cantera/src/ctml.h | 16 +++- 2 files changed, 187 insertions(+), 16 deletions(-) diff --git a/Cantera/src/ctml.cpp b/Cantera/src/ctml.cpp index 283037843..f5fbc3c78 100755 --- a/Cantera/src/ctml.cpp +++ b/Cantera/src/ctml.cpp @@ -287,8 +287,18 @@ namespace ctml { return x; } - - void getFloatArray(const XML_Node& node, vector_fp& v, bool convert) { + /* + * getFloatArray(): + * + * Get an array of floats from the XML Node. The argument field + * is assumed to consist of an arbitrary number of comma + * separated floats, with an arbitrary amount of white space + * separating each field. + * If the node array has an units attribute field, then + * the units are used to convert the floats, iff convert is true. + */ + void getFloatArray(const XML_Node& node, vector_fp& v, bool convert, + string type) { string::size_type icom; string numstr; if (node.name() != "floatArray") @@ -299,16 +309,24 @@ namespace ctml { doublereal vmin = Undef, vmax = Undef; doublereal funit = 1.0; - if (node["units"] != "" && convert) { - funit = toSI(node["units"]); - } + /* + * Get the attributes field, units, from the XML node + */ + string units = node["units"]; + if (units != "" && convert) { + if (type == "actEnergy" && units != "") { + funit = actEnergyToSI(units); + } else if (type != "" && units != "") { + funit = toSI(units); + } + } - if (node["min"] != "") - vmin = atof(node["min"].c_str()); - if (node["max"] != "") - vmax = atof(node["max"].c_str()); + if (node["min"] != "") + vmin = atof(node["min"].c_str()); + if (node["max"] != "") + vmax = atof(node["max"].c_str()); - doublereal vv; + doublereal vv; string val = node.value(); while (1 > 0) { icom = val.find(','); @@ -368,16 +386,39 @@ namespace ctml { } } + /** + * 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 + * + * red:112 blue:34 + * green:banana + * + * + * Returns: + * key val + * 0: "red" "112" + * 1: "blue" "34" + * 2: "green" "banana" + */ void getPairs(const XML_Node& node, vector& key, vector& val) { vector v; getStringArray(node, v); int n = static_cast(v.size()); - string::size_type icolon; + string::size_type icolon; for (int i = 0; i < n; i++) { icolon = v[i].find(":"); if (icolon == string::npos) { - throw CanteraError("getMap","missing colon in map entry (" + throw CanteraError("getPairs","Missing a colon in the Pair entry (" +v[i]+")"); } key.push_back(v[i].substr(0,icolon)); @@ -385,6 +426,128 @@ namespace ctml { } } + /** + * This function interprets the value portion of an XML element + * as a series of "Matrix ids and entries" separated by white space. + * Each pair consists of nonwhite-space characters. + * The first two ":" found in the pair string is used to separate + * the string into three parts. The first part is called the first + * key. The second part is the second key. Both parts must match + * an entry in the keyString1 and keyString2, respectively, + * in order to provide a location to + * place the object in the matrix. + * The third part is called the value. It is expected to be + * a double. It is translated into a double and placed into the + * correct location in the matrix. + * + * Warning: No spaces are allowed in each triplet. Quotes are part + * of the string. + * Example + * keyString = red, blue, black, green + * + * red:green:112 + * blue:black:3.3E-23 + * + * + * + * Returns: + * retnValues(0, 3) = 112 + * retnValues(1, 2) = 3.3E-23 + */ + void getMatrixValues(const XML_Node& node, + const vector& keyString1, + const vector& keyString2, + Array2D &retnValues, bool convert, + bool matrixSymmetric) { + int szKey1 = keyString1.size(); + int szKey2 = keyString2.size(); + int nrow = retnValues.nRows(); + int ncol = retnValues.nColumns(); + if (szKey1 > nrow) { + throw CanteraError("getMatrixValues", + "size of key1 greater than numrows"); + } + if (szKey2 > ncol) { + throw CanteraError("getMatrixValues", + "size of key2 greater than num cols"); + } + if (matrixSymmetric) { + if (nrow != ncol) { + throw CanteraError("getMatrixValues", + "nrow != ncol for a symmetric matrix"); + } + } + + /* + * Get the attributes field, units, from the XML node + * and determine the conversion factor, funit. + */ + doublereal funit = 1.0; + string units = node["units"]; + if (units != "" && convert) { + funit = toSI(units); + } + + string key1; + string key2; + string rmm; + string val; + vector v; + getStringArray(node, v); + int icol, irow; + int n = static_cast(v.size()); + string::size_type icolon; + for (int i = 0; i < n; i++) { + icolon = v[i].find(":"); + if (icolon == string::npos) { + throw CanteraError("getMatrixValues","Missing two colons (" + +v[i]+")"); + } + key1 = v[i].substr(0,icolon); + rmm = v[i].substr(icolon+1, v[i].size()); + icolon = rmm.find(":"); + if (icolon == string::npos) { + throw CanteraError("getMatrixValues","Missing one colon (" + +v[i]+")"); + } + key2 = rmm.substr(0,icolon); + val = rmm.substr(icolon+1, rmm.size()); + icol = -1; + irow = -1; + for (int j = 0; j < szKey1; j++) { + if (key1 == keyString1[j]) { + irow = j; + break; + } + } + if (irow == -1) { + throw CanteraError("getMatrixValues","Row not matched by string: " + + key1); + } + for (int j = 0; j < szKey2; j++) { + if (key2 == keyString2[j]) { + icol = j; + break; + } + } + if (icol == -1) { + throw CanteraError("getMatrixValues","Col not matched by string: " + + key2); + } + double dval = atofCheck(val.c_str()); + dval *= funit; + /* + * Finally, insert the value; + */ + retnValues(irow, icol) = dval; + if (matrixSymmetric) { + retnValues(icol, irow) = dval; + } + } + + } + + /** * This function interprets the value portion of an XML element * as a string. It then separates the string up into tokens diff --git a/Cantera/src/ctml.h b/Cantera/src/ctml.h index ad73d1a58..62821d753 100755 --- a/Cantera/src/ctml.h +++ b/Cantera/src/ctml.h @@ -22,6 +22,7 @@ #include "ct_defs.h" #include "xml.h" +#include "Array.h" using namespace Cantera; namespace ctml { @@ -71,15 +72,22 @@ namespace ctml { string val, string type=""); - void getFloatArray(const XML_Node& node, - vector_fp& v, bool convert=true); + void getFloatArray(const XML_Node& node, vector_fp& v, + bool convert=true, string type=""); void getStringArray(const XML_Node& node, vector& v); void getMap(const XML_Node& node, map& m); - void getPairs(const XML_Node& node, vector& key, vector& val); + void getPairs(const XML_Node& node, vector& key, + vector& val); + void getMatrixValues(const XML_Node& node, + const vector& keyString1, + const vector& keyString2, + Array2D &returnValues, bool convert = true, + bool matrixSymmetric = false); void getIntegers(const XML_Node& node, map& v); - void getFloats(const XML_Node& node, map& v, bool convert=true); + void getFloats(const XML_Node& node, map& v, + bool convert=true); doublereal getFloat(const XML_Node& parent, string name, string type=""); int getInteger(const XML_Node& parent, string name);